Function 调用函数后如何正确返回到主函数?
我试图让下面的内容跳回main,它会打印菜单。 在另一个函数(正常工作)中,我使用了jmp main命令。但是,该函数只打印一条消息,指示它在再次打印菜单之前到达了该函数 如果只使用最后三条线路中的一条,则会出现seg故障错误。如果我一起使用“离开”和“返回”,则相同。我想这和给scanf打电话有关Function 调用函数后如何正确返回到主函数?,function,assembly,return,nasm,Function,Assembly,Return,Nasm,我试图让下面的内容跳回main,它会打印菜单。 在另一个函数(正常工作)中,我使用了jmp main命令。但是,该函数只打印一条消息,指示它在再次打印菜单之前到达了该函数 如果只使用最后三条线路中的一条,则会出现seg故障错误。如果我一起使用“离开”和“返回”,则相同。我想这和给scanf打电话有关 read_int: mov edi, enterintmsg mov eax,0 call printf lea rdi,
read_int:
mov edi, enterintmsg
mov eax,0
call printf
lea rdi, [LC5]
lea rsi, [value]
xor eax,eax
call scanf
mov cl, [value]
jmp main
;leave
;ret
当前代码:
bits 64
global main
extern puts
extern printf
extern scanf
extern get_kb
section.data
;LC0
errormsg: db 'Invalid Input. Enter N,F, or X',0x0D,0x0a,0
;LC1
numequalsmsg: db 'Number equals: '
LC2: db "%d",0
menuprompt: db 0x0D,0x0a,'Enter N to enter an integer from 0 to 20',0x0D,0x0a,'Enter F to display the first N+1 numbers (beginning with zero) on the console',0x0D,0x0a,'Enter X to quit the program',0x0D,0x0a,0
choicemsg: db "Your Choice: ",0
LC5: db "%d",0
;LC6
enterintmsg: db "Enter and integer 0-20: ",0
;LC7
enternummsg: db 'Enter a valid number between 0 and 20',0x0D,0x0a,0
LC8: db " , ",0
LC9: db 'Success!',0x0D,0x0a,0
LC10: db 'In L10!',0x0D,0x0a,0
LC11: db 'In L12!',0x0D,0x0a,0
LC13: db 'In compare to zero section',0x0D,
value: db 0
choice: db 1
.code
main:
;function setup
push rbp
mov rbp, rsp
sub rsp, 16
menu:
;print menu
mov edi, menuprompt
call puts ;display menu
mov edi,choicemsg
;mov eax, 0
;call printf ;display "Your choice:"
call puts
;call getn
;push choice
;push LC5 ;string format
;call scanf ;stores input in choice
;GetLInt [choice]
;mov ebx, choice
;lea rdi, [LC5]
;lea rsi, [choice]
;xor eax,eax
;call scanf
;mov bl, [choice]
call get_kb
mov bl, al
cmp bl, 'N' ;N
je entered_n
cmp bl, 'F' ;F
je correct
cmp bl, 'X' ;X
je correct
;leave
;ret
jmp menu
;ret
correct:
mov edi, LC9
mov eax,0
call printf
jmp menu
;leave
;ret
entered_n:
call read_int
;jmp menu
;leave
jmp menu
read_int:
mov edi, enterintmsg
mov eax,0
call printf
lea rdi, [LC5]
lea rsi, [value]
xor eax,eax
;add esp,4 ;remove parameters
push rsi
push rdi
call scanf
mov cl, [value]
;jmp menu
;leave
ret
;leave
要返回函数,需要使用RET指令。要使RET指令处理返回地址,指令应该跳转到的位置需要位于堆栈的顶部。通常,这个返回地址由CALL指令推送到堆栈上,但是您没有使用CALL指令来调用函数。相反,您使用了
JE read\u int
。这意味着您的函数不知道从何处调用它,因此RET指令无法继续执行之前停止的函数
解决方案是将调用read\u int
的代码更改为如下内容:
cmp bl, 'N'
jne not_n
call read_int
; read_int returns here so put whatever code
; that needs to be executed afterwards here
not_n:
; code handling the case when BL != 'N'
然后,您可以将read_int
更改为使用RET,并将仅RET更改为从函数返回
使用JMP main
返回main函数不起作用,因为它完全按照它所说的那样执行。它跳转到main
的地址,这是main
函数中的第一条指令。这将导致从一开始就再次执行主功能
除非设置堆栈帧,否则不希望使用LEVE指令。您的
read\u int
函数没有设置堆栈帧,因此使用它可能会导致代码崩溃。要返回函数,需要使用RET指令。要使RET指令处理返回地址,指令应该跳转到的位置需要位于堆栈的顶部。通常,这个返回地址由CALL指令推送到堆栈上,但是您没有使用CALL指令来调用函数。相反,您使用了JE read\u int
。这意味着您的函数不知道从何处调用它,因此RET指令无法继续执行之前停止的函数
解决方案是将调用read\u int
的代码更改为如下内容:
cmp bl, 'N'
jne not_n
call read_int
; read_int returns here so put whatever code
; that needs to be executed afterwards here
not_n:
; code handling the case when BL != 'N'
然后,您可以将read_int
更改为使用RET,并将仅RET更改为从函数返回
使用JMP main
返回main函数不起作用,因为它完全按照它所说的那样执行。它跳转到main
的地址,这是main
函数中的第一条指令。这将导致从一开始就再次执行主功能
除非设置堆栈帧,否则不希望使用LEVE指令。您的
read\u int
函数没有设置堆栈帧,因此使用它可能会导致代码崩溃。要返回函数,需要使用RET指令。要使RET指令处理返回地址,指令应该跳转到的位置需要位于堆栈的顶部。通常,这个返回地址由CALL指令推送到堆栈上,但是您没有使用CALL指令来调用函数。相反,您使用了JE read\u int
。这意味着您的函数不知道从何处调用它,因此RET指令无法继续执行之前停止的函数
解决方案是将调用read\u int
的代码更改为如下内容:
cmp bl, 'N'
jne not_n
call read_int
; read_int returns here so put whatever code
; that needs to be executed afterwards here
not_n:
; code handling the case when BL != 'N'
然后,您可以将read_int
更改为使用RET,并将仅RET更改为从函数返回
使用JMP main
返回main函数不起作用,因为它完全按照它所说的那样执行。它跳转到main
的地址,这是main
函数中的第一条指令。这将导致从一开始就再次执行主功能
除非设置堆栈帧,否则不希望使用LEVE指令。您的
read\u int
函数没有设置堆栈帧,因此使用它可能会导致代码崩溃。要返回函数,需要使用RET指令。要使RET指令处理返回地址,指令应该跳转到的位置需要位于堆栈的顶部。通常,这个返回地址由CALL指令推送到堆栈上,但是您没有使用CALL指令来调用函数。相反,您使用了JE read\u int
。这意味着您的函数不知道从何处调用它,因此RET指令无法继续执行之前停止的函数
解决方案是将调用read\u int
的代码更改为如下内容:
cmp bl, 'N'
jne not_n
call read_int
; read_int returns here so put whatever code
; that needs to be executed afterwards here
not_n:
; code handling the case when BL != 'N'
然后,您可以将read_int
更改为使用RET,并将仅RET更改为从函数返回
使用JMP main
返回main函数不起作用,因为它完全按照它所说的那样执行。它跳转到main
的地址,这是main
函数中的第一条指令。这将导致从一开始就再次执行主功能
除非设置堆栈帧,否则不希望使用LEVE指令。您的
read\u int
函数没有设置堆栈帧,因此使用它可能会导致代码崩溃。为什么要跳转到main
并放弃当前堆栈帧等?main
是否重置堆栈指针?确实如此。我将其设置为where main仅设置堆栈帧,然后调用了menu,但无法使其离开任一函数返回到menu。将其更改回where main仅设置堆栈。在打印成功函数后调用菜单函数,但是如果我校准上面的read_int函数,仍然会得到seg fault错误。C