从标准输入将数字读入寄存器?加载 scanf 结果

Posted

技术标签:

【中文标题】从标准输入将数字读入寄存器?加载 scanf 结果【英文标题】:Reading a number into a register from stdin? Loading a scanf result 【发布时间】:2012-06-04 12:30:58 【问题描述】:

我目前正忙于组装,遇到了以下问题:

我正在尝试获取已输入 eax 寄存器的数字。首先我提出一个要求输入的字符串,然后有人必须输入一个数字。

我使用了以下代码,但我并没有完全理解它。请注意代码中的 cmets。

我知道这个数字现在绝对没有任何反应,除了它已被移入 eax。我想知道的是为什么我必须使用 leal:它为什么以及它的作用是什么?为什么我需要将 eax 推回堆栈?

.text
string1: .asciz "Please enter a number\n"
input: .asciz "%d" 

.global main
main:
       # Editor's note: this code is broken / unsafe; missing push %ebp here
  movl %esp, %ebp
  
  push $string1          # prompt string
  call printf            #print the string
           # no add $4, %esp here: 4 bytes still allocated on the stack

  leal -4(%ebp), %eax   # ????
  pushl %eax            # the thing you pushed in eax is now pushed on the stack?
  pushl $input          #the number 
  
  call scanf      
  
  popl %eax
  popl %eax       # the number that has been entered is now in eax
  
  call end
  
end:
  push $0
  call exit

【问题讨论】:

请注意 push %esp 可以替换 lea / push %eax 因为 ESP 指向第一个 push $string1 保留的 4 个字节。根本不需要使用帧指针,因此可以删除损坏的mov %esp, %ebp。 (因为您没有保存/恢复 EBP 而损坏,但在标准调用约定中它是保留调用的)。 此外,对于在调用函数之前需要 16 字节 ESP 对齐的现代系统,此代码也不安全。 (例如 Linux 上的 i386 System V ABI,但不是大多数其他操作系统。) 【参考方案1】:

您正在调用函数,因此您在堆栈上将参数传递给它们。一个整数在eax 中返回给您,其余的是通过输入-输出指针参数再次在堆栈上。查看x86 calling conventions

编辑0:

leal 指令将某个临时变量(scanf 放置整数值的位置)的有效地址存储到eax,然后将其传递给堆栈上的scanf。看这里:What's the purpose of the LEA instruction?

【讨论】:

好的,但是 leal 到底是做什么的呢?

以上是关于从标准输入将数字读入寄存器?加载 scanf 结果的主要内容,如果未能解决你的问题,请参考以下文章

如何在C语言中不指定数组大小的情况下将数字读入数组

c++第二遍scanf读入问题

scanf(%d),连续输入数字和字符(一条无空格字符串)

scanf(%d),连续输入数字和字符(一条无空格字符串)

scanf函数

从标准输入将原始类型的值读入变量