Assembly 在nasm汇编中调用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

在下面,我将尝试获得用户的选择,并使用它调用其他函数。我将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:   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字节的整数。