【问题标题】:How to use data stored in register when calling scanf in nasm assembly在nasm程序集中调用scanf时如何使用存储在寄存器中的数据
【发布时间】:2015-07-20 17:54:34
【问题描述】:

在下文中,我试图获取用户的选择并使用它来调用其他函数。我将选择压入堆栈,然后压入格式行,然后调用 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 .datasection .text 而不是将所有内容都放在只读的.text 部分,因为您希望 scanf 将结果存储在那里。我为您解决了这个问题,因为这个旧问题和答案与这些错误无关。)

【问题讨论】:

  • 你可能想要mov bl, [choice] - 只有一个字节。
  • 请参阅stackoverflow.com/tags/x86/info 了解有关将 gdb 与程序集结合使用的信息,以防您没有良好的调试设置。

标签: assembly nasm x86-64 calling-convention


【解决方案1】:

您使用了错误的约定。显然你知道你应该做什么,因为你打电话给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])。

【讨论】:

  • 将其更改为 %d 并尝试通过键入 cmp BYTE [choice] 来查看用户是否输入了“N”,与 70 和 88 相比,78 也具有相同的命令。出于某种原因,它显示即使每个数字(或更确切地说是字母)应该跳转到不同的函数,所有可能的跳转到函数。如果我用 [bl] 替换 [choice],我会得到无效的有效地址。有什么建议吗?
  • 如果您使用%d,那么scanf 将需要一个数字,而N 不是一个数字,因此您不会得到任何结果。此外,%d 将需要一个 4 字节整数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2012-06-13
相关资源
最近更新 更多