无法在汇编中实现简单的算术程序

时间:2011-11-25 09:25:17

标签: assembly x86 masm

我正在尝试在汇编中实现以下程序:

int number;
printf("\n%s","Enter an integer: ");
scanf("%d",&number);
number=7-number*3;
printf("\n%s%d\n\n","The integer is: ",number);

到目前为止,我的尝试是:

    .386
    .model flat, c
    .stack 100h
printf PROTO arg1:Ptr Byte, printlist:VARARG
scanf PROTO arg2:Ptr Byte, printlist:VARARG
    .data
in1fmt byte "%d",0
msg1fmt byte 0Ah,"%s",0
msg1 byte "Enter an integer: ",0
msg2fmt byte 0Ah,"%s%d",0Ah,0Ah,0
msg2 byte "The integer is: ",0
number sdword ?
    .code
main proc
    INVOKE printf, ADDR msg1fmt, ADDR msg1
    INVOKE scanf, ADDR in1fmt, ADDR number
    mov eax, number
    mov ebx, 3
    imul ebx
    mov number, eax
    mov eax, 7
    sub eax, number
    INVOKE printf, ADDR msg2fmt, ADDR msg2, eax
    ret
main endp
    end

第一个问题似乎是eax没有存储在数量中。当我将eax输入数字后打印出数字值时,输出值为21,输入为30. eax为90,但将eax移入数字后为21。

我确定我错过了一些简单的事情,但我无法看清楚我的错误。

1 个答案:

答案 0 :(得分:0)

enterMsg db 'Enter an integer: ',0
resultMsg db 'The integer is: %d\r\n',0    ; yep, I refactored this one

stringPattern db '%s',0

; ...


proc main
    push ebp
    mov ebp,esp
    sub esp,4

    lea eax,[ds:enterMsg]
    push eax
    lea eax,[ds:stringPattern]
    push eax
    call printf    ; printf("%s", enterMsg); // btw, why?
    add esp,8


    lea eax,[ebp - 4]
    push eax
    lea eax,[ds:intPattern]
    push eax
    call scanf     ; scanf("%d", &number);
    add esp,8

    mov eax,[dword ptr ss:ebp - 4]
    push eax
    call calculate    ; number = calculate(number);
    add esp,4
    mov [dword ptr ss:ebp - 4],eax

    lea eax,[ebp - 4]
    push eax
    lea eax,[ds:resultMsg]
    push eax
    call printf    ; printf(resultMsg, number);
    add esp,8

    mov esp,ebp
    pop ebp
    ret
endp main


; number=7-number*3;
proc calculate
    push ebp
    mov ebp,esp
    push ebx

    ; not considering integer overflow for now
    mov eax,[dword ptr ss:ebp + 8]
    mov ebx,3
    imul ebx
    neg eax
    add eax,7

    pop ebx
    mov esp,ebp
    pop ebp
    ret
endp calculate

C程序很容易转换为ASM。 使用 cdecl 调用约定,您可以从右向左推送子例程的参数,调用子例程,并在eax中获取返回值(如果有的话;或者ST0用于浮点数)。然后你清理堆栈,就是这样。

我认为问题是你在堆栈上推送结果的值而不是指向它的指针。但不确定;我已经有一段时间没在ASM中使用C rtl了