1. 程式人生 > >彙編學習---子程式之call的四種引數傳遞

彙編學習---子程式之call的四種引數傳遞

題目要求:

現在有一個數組,內容為34h,78h,0afh,8ah,要求主程式安排並存放其結果,並由子程式來完成求陣列元素的效驗和。請編寫一段程式,採用段內呼叫子程式實現。

  •    分別實現用暫存器,變數,堆疊,利用call後續區四種方式傳參。
  •     所謂效驗和是指:不記進位的累加。

題目分析:

本題主要屬於子程式設計,只需按照要求在設計一個求一段記憶體資料的效驗和的子程式即可。

程式碼實現:

1.暫存器傳參實現:

data segment

ARRAY  db 34h,78h,0afh,8ah      ;資料準備,及需要進行校驗和的陣列

COUNT equ $-ARRAY                 ;儲存陣列中的資料個數

RESULT db ?                             ;定義一個RESULT的結果變數,用於儲存校驗和結果

data ends
code segment

assume cs:code,ds:data

start:

mov ax,data

mov ds,ax

mov bx,offset ARRAY                  ;陣列的起始偏移地址賦給bx

mov cx,COUNT                          ;將陣列數字的個數賦值給cx,確定迴圈的次數

call CHECKSUM                         ;段內呼叫子程式,實現計算校驗和

mov RESULT,al                          ;並將結果存在RESULT變數中

mov ax,4c00h

int 21h

;子程式CHECKSUM
;功能:求陣列元素的校驗和
;入口:bx->陣列的入口偏移地址;cx->陣列元素個數
;出口:al->校驗和

CHECKSUM proc

xor al,al

    SUM:

add al,[bx]

inc bx

loop SUM

ret

CHECKSUM endp
code ends

end start

---------------------------------------------------------------------------------快樂分隔線----------------------------------------------------------------------------

2.變數傳叄實現:

data segment

ARRAY  db 34h,78h,0afh,8ah     ;資料準備,及需要進行校驗和的陣列

COUNT equ $-ARRAY                 ;儲存陣列中的資料個數

RESULT db ?                             ;定義一個RESULT的結果變數,用於儲存校驗和結果

data ends
code segment

assume cs:code,ds:data

start:

mov ax,data

mov ds,ax

call CHECKSUM                        ;段內呼叫子程式,實現計算校驗和

mov ax,4c00h

int 21h

;子程式CHECKSUM
;功能:求陣列元素的校驗和
;入口:陣列的偏移地址,以及陣列元素個數
;出口:校驗和結果儲存在RESULT變數中
CHECKSUM proc

push ax                                   ;暫存器的保護

push bx

push cx

xor al,al

mov bx,offset ARRAY              ;陣列的起始偏移地址賦給bx

mov cx,COUNT                        ;將陣列數字的個數賦值給cx,確定迴圈的次數

    SUM:

add al,[bx]

inc bx

loop SUM

mov RESULT,al                      ;並將結果存在RESULT變數中

pop cx                                   ;暫存器的恢復

pop bx

pop ax 

ret

CHECKSUM endp
code ends

end start

---------------------------------------------------------------------------------快樂分隔線----------------------------------------------------------------------------

3.堆疊傳參實現:

data segment

ARRAY  db 34h,78h,0afh,8ah        ;資料準備,及需要進行校驗和的陣列

COUNT equ $-ARRAY                    ;儲存陣列中的資料個數

RESULT db ?                                ;定義一個RESULT的結果變數,用於儲存校驗和結果

data ends
code segment

assume cs:code,ds:data

start:

mov ax,data

mov ds,ax

mov ax,offset ARRAY                  ;陣列的起始偏移地址賦給ax

push ax                                       ;將陣列的偏移地址壓入堆疊

mov ax,COUNT                           ;將陣列數字的個數賦值給ax

push ax                                      ;將陣列元素個數壓入堆疊

call CHECKSUM                          ;段內呼叫子程式,實現計算校驗和

mov ax,4c00h

int 21h

;子程式CHECKSUM
;功能:求陣列元素的校驗和
;入口:將陣列首地址和陣列元素個數壓入堆疊
;出口:校驗和結果儲存在RESULT變數中
CHECKSUM proc

push bp                                       ;暫存器保護

push bx

push cx

mov bp,sp

mov bx,[bp+10]

mov cx,[bp+8]

xor al,al

    SUM:

add al,[bx]

inc bx

loop SUM

mov RESULT,al                        ;並將結果存在RESULT變數中

pop cx

pop bx

pop bp

ret+4                                        ;注意因為一開始就向堆疊中壓入了兩個值,所以此處應該平衡堆疊

CHECKSUM endp
code ends
end start

ps:注意,通過實驗發現,函式通過堆疊實現函式的引數傳遞的時候,堆疊中只儲存了呼叫函式指令的下條指令的偏移地址,並沒有連同段地址儲存。我也不太清楚是什麼原因。一開始由於不知道這個原因,所以在通過堆疊給bx,cx暫存器賦值的時候,總是出錯。

---------------------------------------------------------------------------------快樂分隔線----------------------------------------------------------------------------

4.利用call後續區

data segment

ARRAY  db 34h,78h,0afh,8ah         ;資料準備,及需要進行校驗和的陣列

COUNT equ $-ARRAY                     ;儲存陣列中的資料個數

RESULT db ?                                ;定義一個RESULT的結果變數,用於儲存校驗和結果

data ends
code segment

assume cs:code,ds:data

start:

mov ax,data

mov ds,ax

call CHECKSUM                           ;段內呼叫子程式,實現計算校驗和

dw offset ARRAY                         ;call函式後面的資料區

mov ax,4c00h

int 21h

;子程式CHECKSUM
;功能:求陣列元素的校驗和
;入口:將陣列首地址和陣列元素個數壓入堆疊
;出口:校驗和結果儲存在RESULT變數中
CHECKSUM proc

push bp

push bx

push cx

mov bp,sp

mov si,[bp+6]

mov bx,cs:[si]                            ;通過壓入的下一條指令取得後繼區的資料

mov cx,COUNT

xor al,al

    SUM:

add al,[bx]

inc bx

loop SUM

mov RESULT,al                       ;並將結果存在RESULT變數中

pop cx

pop bx

pop bp

ret

CHECKSUM endp
code ends

end start

ps:關於此種通過call後續區傳遞引數不是很常用,所以在這裡就簡單的通過傳遞陣列的偏移地址簡單演示其過程。