程序集中的堆栈溢出错误

时间:2018-05-10 00:40:30

标签: assembly 64-bit

我正在尝试编写从用户获取输入并在程序集x64中显示阶乘的代码。每次运行代码时,它都会在finalProjectAssembly.exe中给出0x00007FF64B910B11处的未处理异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001,0x00000019F1603FF8)。但我不明白堆栈是如何溢出的。我错过了什么?

INCLUDELIB libcmt.lib
INCLUDELIB legacy_stdio_definitions.lib

EXTERN printf:PROC
EXTERN scanf:PROC

.DATA
prompt  BYTE    "Enter a number: ", 0
inFmt   BYTE     "%d", 0
prompt3 BYTE    "The factorial is: %d",10,0
cont    QWORD   ?
disp    BYTE    "You Entered %d", 10,0
num     QWORD   ?
num2    REAL8   1.5

.CODE
main PROC C
sub     rsp, 24
lea     rcx, prompt          
call    printf
lea     rdx, num             
lea     rcx, inFmt           
call    scanf
push    num

mov     rdx,num              
lea     rcx, disp            
call    printf
call    factorial
mov     rdx, rax
lea     rcx, prompt3
call    printf

lea     rcx, prompt2
call    printf
lea     rdx, cont
lea     rcx, inFmt
call    scanf

add     rsp,24             
mov     rax,0
ret
main ENDP

factorial PROC
push    rbp
mov     rbp,rsp
mov     rax, [rbp + 16]
cmp     rax, 1
jle     quit
dec     rax 
push    rax
call    factorial
mov     rbx, [rbp+16]
imul    rbx

quit:
mov     rsp, rbp
pop     rbp
ret
factorial ENDP

1 个答案:

答案 0 :(得分:0)

如果您拨打外国函数(printfscanf),必须遵守其调用约定。适当的Microsoft x64 software convention确定在调用函数之前必须在堆栈空间中保留堆栈中的四个qwords(= 32字节)。该功能可以自由使用“阴影空间”。此外,ESP必须与可被16整除的地址对齐。

更改

sub     rsp, 24

sub     rsp, 32
and     spl, -16        ; Align to 16

add rsp,24函数末尾不需要main。正确的序言(push rbp; mov rsp, rbp)和正确的结尾(leave)将由汇编程序ML64自动插入。

阴影空间必须在call指令推送的函数返回地址前面笔直。将push num移近call factorial,不要忘记清理堆栈:

push    num
call    factorial
add     rsp, 8

不要忘记清理堆栈:

push    rax
call    factorial
add     rsp, 8

我没有按照David Wohlferd的建议检查格式说明符%d。该程序基本上适用于上述变化。