Assembly 在nasm汇编中调用scanf时如何使用寄存器中存储的数据
在下面,我将尝试获得用户的选择,并使用它调用其他函数。我将choice推到堆栈上,然后推格式行,然后调用scanf,但我似乎无法使用输入的内容Assembly 在nasm汇编中调用scanf时如何使用寄存器中存储的数据,assembly,nasm,x86-64,calling-convention,Assembly,Nasm,X86 64,Calling Convention,在下面,我将尝试获得用户的选择,并使用它调用其他函数。我将choice推到堆栈上,然后推格式行,然后调用scanf,但我似乎无法使用输入的内容 ;nasm -f elf64 fib.asm -o fib.o ;gcc -S -masm=intel fib.c -o fib.s ;./fib bits 64 global main extern puts extern printf extern scanf section .data errormsg: d
;nasm -f elf64 fib.asm -o fib.o
;gcc -S -masm=intel fib.c -o fib.s
;./fib
bits 64
global main
extern puts
extern printf
extern scanf
section .data
errormsg: db 'Invalid Input. Enter N,F, or X',0x0D,0x0a,0
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 "%s",0
enterintmsg: db "Enter and integer 0-20: ",0
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: dw 0
choice: dw 0
section .text
main:
menu:
push rbp
mov rbp, rsp
sub rsp, 16
mov edi, menuprompt
call puts ;display menu
mov edi,choicemsg
mov eax, 0
call printf ;display "Your choice: "
;call getn
push choice
push LC5 ;string format
call scanf ;stores input in choice
;GetLInt [choice]
mov ebx, choice
cmp ebx, 78
je correct
correct:
mov edi, ebx
mov eax,0
call printf
(编者按:
section.data
只是像foo.bar:
一样的标签声明,.code
也是如此。可能您想要section.data
和section.text
而不是将所有内容都放在只读节中,因为您希望scanf将结果存储在那里。我为您解决了这个问题因为这个老问题和答案与这些错误无关。)您使用了错误的约定。显然,您知道应该怎么做,因为调用printf
没有问题。调用scanf
也应该使用相同的约定-您使用的堆栈参数传递是32位约定,64位使用寄存器。类似如下:
lea rdi, [LC5] ; 1st arg = format
lea rsi, [choice] ; 2nd arg = address of buffer
xor eax, eax ; no xmm registers
call scanf ; stores input in choice
顺便说一下,使用具有2字节空间的无约束%s
是个坏主意
另外,按照弗兰克说的做,即加载一个字节(mov-bl,[choice]
)当您想要处理输入时。您使用了错误的约定。显然,您知道应该怎么做,因为调用printf
没有问题。调用scanf
也应该使用相同的约定-您使用的堆栈参数传递是32位约定,64位使用寄存器。类似于这:
lea rdi, [LC5] ; 1st arg = format
lea rsi, [choice] ; 2nd arg = address of buffer
xor eax, eax ; no xmm registers
call scanf ; stores input in choice
顺便说一下,使用具有2字节空间的无约束%s
是个坏主意
另外,按照弗兰克说的做,即加载一个字节(mov-bl,[choice]
)当您想要处理输入时。您使用了错误的约定。显然,您知道应该怎么做,因为调用printf
没有问题。调用scanf
也应该使用相同的约定-您使用的堆栈参数传递是32位约定,64位使用寄存器。类似于这:
lea rdi, [LC5] ; 1st arg = format
lea rsi, [choice] ; 2nd arg = address of buffer
xor eax, eax ; no xmm registers
call scanf ; stores input in choice
顺便说一下,使用具有2字节空间的无约束%s
是个坏主意
另外,按照弗兰克说的做,即加载一个字节(mov-bl,[choice]
)当您想要处理输入时。您使用了错误的约定。显然,您知道应该怎么做,因为调用printf
没有问题。调用scanf
也应该使用相同的约定-您使用的堆栈参数传递是32位约定,64位使用寄存器。类似于这:
lea rdi, [LC5] ; 1st arg = format
lea rsi, [choice] ; 2nd arg = address of buffer
xor eax, eax ; no xmm registers
call scanf ; stores input in choice
顺便说一下,使用具有2字节空间的无约束%s
是个坏主意
另外,按照Frank说的做,即当你想处理输入时,加载一个字节(mov-bl,
)。你可能想要mov-bl,
-只有一个字节。如果你没有很好的调试设置,请参阅以获取有关将gdb与汇编一起使用的信息。你可能想要mov-bl,[choice]
-只有一个字节。如果调试设置不好,请参阅以获取有关将gdb与汇编一起使用的信息。您可能需要mov bl,[choice]
-只有一个字节。如果调试设置不好,请参阅以获取有关将gdb与汇编一起使用的信息。您可能需要mov bl,[choice]
-只有一个字节。有关在程序集中使用gdb的信息,请参阅,以防调试设置不好。将其更改为%d,然后尝试通过键入cmp byte[选项]查看用户是否输入了“N”与70和88相比,78也有相同的命令。出于某种原因,它显示了所有可能跳转到函数的情况,即使每个数字(或字母)应该跳转到不同的数字。如果我将[choice]替换为[bl]我得到无效的有效地址。有什么建议吗?如果您使用%d
,则scanf
将需要一个数字,N
不是一个数字,因此您不会得到任何结果。此外,%d
将需要一个4字节的整数。将其更改为%d,并尝试通过键入cmp字节来查看用户是否输入了“N”[选项]与70和88相比,78也有相同的命令。出于某种原因,它显示了所有可能跳转到函数的情况,即使每个数字(或字母)应该跳转到不同的数字。如果我将[choice]替换为[bl]我得到无效的有效地址。有什么建议吗?如果您使用%d
,则scanf
将需要一个数字,N
不是一个数字,因此您不会得到任何结果。此外,%d
将需要一个4字节的整数。将其更改为%d,并尝试通过键入cmp字节来查看用户是否输入了“N”[选项]与70和88相比,78也有相同的命令。出于某种原因,它显示了所有可能跳转到函数的情况,即使每个数字(或字母)应该跳转到不同的数字。如果我将[choice]替换为[bl]我得到无效的有效地址。有什么建议吗?如果您使用%d
,则scanf
将需要一个数字,N
不是一个数字,因此您不会得到任何结果。此外,%d
将需要一个4字节的整数。将其更改为%d,并尝试通过键入cmp字节来查看用户是否输入了“N”[选项]与70和88相比,78也有相同的命令。出于某种原因,它显示了所有可能跳转到函数的情况,即使每个数字(或字母)应该跳转到不同的数字。如果我将[choice]替换为[bl]我得到无效的有效地址。有什么建议吗?如果使用%d
,则scanf
将需要一个数字,N
不是一个数字,因此不会有任何结果。此外,%d
将需要一个4字节的整数。