【问题标题】:Storing values in eax in assembly在汇编中将值存储在 eax 中
【发布时间】:2015-12-11 06:26:22
【问题描述】:
extern printf                ; the C function, to be called

SECTION .data                ; Data section, initialized variables
a: dd 5                      ; int a=5;
fmt: db "a=%d, eax=%d",10,0  ; The printf format, "\n",'0'

SECTION .text                ; Code section.

global main                  ; the standard gcc entry point
main:                        ; the program label for the entry point

   push ebp                  ; calling convention
   mov ebp, esp

   mov eax, [a]              ; put a from store into register
   add eax, 2                ; a+2
   push eax                  ; value of a+2
   push dword [a]            ; value of variable a
   push dword fmt            ; address of ctrl string
   call printf               ; Call C function
   add  esp, 12              ; pop stack 3 push times 4 bytes

   mov esp, ebp              ; returning convention
   pop ebp                   ; same as "leave" op

   mov eax,0                 ;  normal (no error) return value
   ret                       ; return

我有点糊涂了。我知道dd 声明了一个 4 字节的值并在其中存储了 5。

1) 然后mov eax, [a] 将其存储在 eax 寄存器中。但是 AX 不只是一个 2 字节的寄存器。它如何存储一个 4 字节的值?

2) fmt: db "a=%d, eax=%d",10,0 我知道 fmt 是一个位置名称,而 db 声明了一个字节,但是剩下的代码是做什么的呢?

【问题讨论】:

  • E 代表扩展。 EAX 存储 32 位。
  • 关于 #2,我建议您查找有关 printf 函数如何处理格式字符串的信息。

标签: assembly


【解决方案1】:

术语:从内存中读取 (add eax, [a]) 是一种“负载”。写入内存是一种“存储”(mov [a], eax)。

不过,dd 指令在这个意义上并没有“存储”。当您的程序启动时,数据已经存在。使用“puts”或“places”之类的词来避免使用“store”,这在此上下文中具有技术含义。


  1. eax 是 4B。 axeax 的低2 字节,就像alax 的低字节一样。请参阅 wiki 上的链接。我认为维基百科的 x86 文章有一个寄存器图,显示了寄存器子集的名称。 (rdi / edi / di / dilrdi/dil 仅在 64 位模式下可用)、EFLAGS 等)

  2. "string", 10, 0 是一个带有换行符和终止零字节的字符串。


   push ebp                  ; calling convention
   mov ebp, esp

制作堆栈帧不是“调用约定”的一部分。现在 gcc 默认为 -fomit-frame-pointer,因为现代调试信息格式允许堆栈回溯以进行调试和异常处理,即使没有它。制作堆栈帧是 ABI 的可选部分,但严格来说不是您所谓的“调用约定”的一部分。该术语的含义仅限于函数在哪里找到它们的 args,以及它们如何返回它们,除非我弄错了。

【讨论】:

  • , 10, 0 部分是必需的,还是只是为了使 printf 输出看起来不错?
  • @Everythingsucks:如果你想要换行,10 是必要的。在 Hello World 程序中省略 \n,您自己看看。当然,0 是绝对必要的。 C 字符串的结尾仅由零字节标记;其他任何地方都没有存储长度供 printf 知道字符串的结束位置。
猜你喜欢
  • 2019-12-26
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 2019-07-05
  • 2017-10-27
  • 1970-01-01
相关资源
最近更新 更多