2012-06-24 59 views
0

寫一個NASM宏:divide,有2個參數,它指定任何尋址模式中的無符號整數。宏計算第一個參數的上限,除以第二個參數,並將結果放入寄存器edx中。如果第二個參數是0(要在運行時測試),結果應該是0,並且應該將消息「除以零」輸出到stdout。NASM宏處理任何尋址模式

我怎麼知道哪個是哪個,所以我們可以處理每個案例? (;地址模式是:註冊,內存和直接的。)

編輯: 這是最後的代碼,我寫道: 如何編寫不帶標籤的代碼? (位置獨立代碼):

%macro divide 2 

section .rodata 
     LC1: DB "divide by zero ", 10, 0 

section .text 

    mov eax, %1 
    mov ebx, %2 
    cmp ebx, 0 ; divide by zero 
    jne rest1 
    push LC1 
    call printf 
    add esp,4 
    mov edx, 0 
    jmp end1 

rest1: 
    mov edx, 0 
    div ebx 
    add eax, edx 
    mov edx , eax ; the result should be in edx 

end1: 
%endmacro 

回答

1

你不需要告訴哪個是哪個。通過任何位置的MOV指令(另一個寄存器,內存,立即數)可以加載通用寄存器,例如EAX。利用這一點。

編輯

爲了使它更清楚,這是你怎麼能寫這樣的宏:

%macro mydiv 2 
    mov eax, %1 
    mov ebx, %2 
    mov edx, 0 
    div ebx 
%endmacro 

這是你將如何使用它:

mydiv 3, 2 ; 2 immediate operands 

    mov ebx, 15 
    mov ecx, 3 
    mydiv ebx, ecx ; 2 register operands 

    mydiv [dividend], [divisor] ; 2 memory operands 

... 

    dividend dd 42 
    divisor dd 6 

當然,宏的定義方式對分割操作數的位置有一定的限制。例如,操作數2(除數)不能在EAX中,因爲mov ebx, eax將加載EBX與操作數1(除數),因爲前面的指令mov eax, %1會將除數分配給EAX

您可以解決通過使用堆棧:

%macro mydiv2 2 
    push ebx 
    push %1 
    push %2 
    pop ebx 
    pop eax 
    mov edx, 0 
    div ebx 
    pop ebx 
%endmacro 

這個宏將接受來自任何寄存器就好的除數和被除數,它不會垃圾EBX。 /都將是唯一的(未成年人)與它的問題,當你操作數(S)是在內存中,相對於ESP解決,例如:

mydiv2 eax, [esp+8] 

那些推動改變ESP和必須被考慮在內。

EDIT2

還有一個警告與mydiv2 ...這將推動立即數(如123)如在16位模式的16位和32位模式的32位,但將將它們彈出爲32位。要在16位模式mydiv2工作你需要用dword前綴立即常量:

mydiv2 dword 3, dword 2 ; 2 immediate operands 

現在可以實現宏的功能需要休息。

+0

但eax可以是一個值,可以是一個地址。沒有? – user1462787

+0

'EAX'是一個註冊表。它可以包含不同的值。一般來說,這些是否是地址取決於您。在宏中只有'MOV寄存器,參數'。當你調用這個宏時,這個參數可以是123,ECX,[EBX * 4 + EDI-3],無論你想要什麼。 –

+0

查看已更新的答案。 –