КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА - Турбо С: руководство пользователя. Часть 2 - Стр. 45

Индекс материала
Турбо С: руководство пользователя. Часть 2
Стр. 2
Стр. 3
Стр. 4
Стр. 5
Стр. 6
Стр. 7
Стр. 8
Стр. 9
Стр. 10
Стр. 11
Стр. 12
Стр. 13
Стр. 14
Стр. 15
Стр. 16
Стр. 17
Стр. 18
Стр. 19
Стр. 20
Стр. 21
Стр. 22
Стр. 23
Стр. 24
Стр. 25
Стр. 26
Стр. 27
Стр. 28
Стр. 29
Стр. 30
Стр. 31
Стр. 32
Стр. 33
Стр. 34
Стр. 35
Стр. 36
Стр. 37
Стр. 38
Стр. 39
Стр. 40
Стр. 41
Стр. 42
Стр. 43
Стр. 44
Стр. 45
Стр. 46
Стр. 47
Стр. 48
Стр. 49
Стр. 50
Стр. 51
Стр. 52
Стр. 53
Стр. 54
Стр. 55
Стр. 56
Все страницы
          В этом  случае  будут не только выполняться far-вызовы подп-          
     рограмм,  но и передавемые указатели так же будут far.  Модифици-          
     руйте вашу программу таким образом, чтобы она включала в себя но-          
     вый файл заголовка:                                                        
                                                                                
         #include 
     из стека параметры,  так как это  сделает  вызывающая  программа.          
     Например,  программа на ассемблере, созданная транслятором из ис-          
     ходной программы на Си, для главной функции выглядит так:                  
                                                                                
          mov  word ptr [bp-8],5            ; i = 5                             
                                                                                
          mov  word ptr [bp-6],7            ; j = 7                             
          mov  word ptr [bp-2],0014h        ; k = 0x1407AA                      
          mov  word ptr [bp-4],07AAh                                            
          push word ptr [bp-2]              ; Push старший полубайт k           
          push word ptr [bp-4]              ; Push младший полубайт k           
          push word ptr [bp-6]              ; Push j                            
          push word ptr [bp-8]              ; Push i                            
          call near ptr funca               ; вызов funca (push addr)           
          add sp,8                          ; восстановить стек                 
                                                                                
          Обратим внимание на последнюю команду:  add sp,8. Транслятор          
     знает, сколько параметров помещено в стеке в данный момент; кроме          
     того он знает, что адрес возврата, помещенный в стек во время вы-          
     зова funca, уже вынут из него командой ret в конце funca.                  
                                                                                
                                                                                
                                                                                
           Последовательность передачи параметров типа Паскаль                  
     -----------------------------------------------------------------          
                                                                                
          Другой метод  передачи  параметров  - стандартный метод типа          
     Паскаль (известный также как Паскаль-соглашение  по  вызову).  Но          

                         - 373,374 -
                                                                                
     нельзя  сказать,  что вы можете вызывать функции Турбо Паскаля из          
     Турбо Си: это неверно. Рассматриваемая последовательность заносит          
     параметры слева направо;  таким образом, если funca объявлена как          
                                                                                
          void pascal funca (int p1, int p2, int p3 );                          
                                                                                
     то при  вызове этой функции параметры в стек заносятся слева нап-          
     раво (p1, p2, p3), а следом за ними в стек помещается адрес возв-          
     рата. Таким образом, если вы даете вызов                                   
                                                                                
          main ()                                                               
          {                                                                     
             int i,j;                                                           
             long k;                                                            
             ...                                                                
             i = 5;  j = 7;  k = 0x1407AA;                                      
             funca(i,j,k);                                                      
             ...                                                                
          }                                                                     
                                                                                
     то стек будет выглядеть так (в момент перед занесением в стек ад-          
     реса возврата):                                                            
                                                                                
                                                                                
           SP+06:   0005  i = p1                                                
           SP+04:   0007  j = p2                                                
           SP+02:   0014                                                        
           SP:      07AA  k = p3                                                
                                                                                
          В чем  же проявляется отличие такого типа последовательности          
     передачи параметров от рассмотренного ранее?  Кроме изменения по-          
     рядка занесения параметров,  последовательность передачи парамет-          
     ров типа Паскаль предполагает, что вызванная подпрограмма (funca)          
     знает,  сколько параметров передано и, соответственно, помещено в          
     стек.  Другими словами,  подпрограмма вызова funca на  ассемблере          
     теперь выглядит так:                                                       
                                                                                
          push  word  ptr[bp-8]             ; Push i                            
          push  word ptr [bp-6]             ; Push j                            
          push  word ptr [bp-2]             ; Push старший байт k               
          push  word ptr [bp-4]             ; Push младший байт k               
          call  near ptr funca              ; вызов funca (Push addr)           
                                                                                
          Заметим, что здесь нет команды add sp,8 после вызова. Вместо          
     этого funca использует команду ret 8  при  завершении  для  того,          

                         - 375,376 -
                                                                                
     чтобы  очистить  стек  перед  возвратом к main.  По умолчанию все          
     функции,  написанные на Турбо Си, используют метод передачи пара-          
     метров типа Си. Исключение составляет случай, когда вы используе-          
     те -р опцию транслятора (соглашение по  вызову...Паскаль),  когда          
     все функции используют метод типа Паскаль. В этой ситуации вы мо-          
     жете заставить нужную функцию применить метод передачи параметров          
     типа Си с помощью модификатора cdecl:                                      
                                                                                
          void cdecl funca (int p1, int p2, int p3);                            
                                                                                
          Этот  оператор  игнорирует -p опцию.                                  
                                                                                
          Зачем вообще нужно Паскаль-соглашение по вызову? По трем ос-          
     новным соображениям:                                                       
                                                                                
          - Вы можете быть вызваны подпрограммой, написаной на ассемб-          
     лере, которая использует данное соглашение по вызову.                      
                                                                                
          - Вы можете быть вызваны подпрограммами,  написаными на дру-          
     гих языках.                                                                
                                                                                
          - Вызов создаваемой программы будет менее  громоздким,  пос-          
                                                                                
     кольку теперь не нужно очищать стек после ее окончания.