[英]In x86, why do I have the same instruction two times, with reversed operands?
I am doing several experiments with x86
asm trying to see how common language constructs map into assembly. 我正在尝试使用
x86
asm进行多次实验,试图了解常见语言如何构建映射到汇编。 In my current experiment, I am trying to see specifically how C language pointers map to register-indirect addressing. 在我目前的实验中,我试图具体了解C语言指针如何映射到寄存器间接寻址。 I have written a fairly hello-world like pointer program:
我写了一个像指针程序一样的hello-world:
#include <stdio.h>
int
main (void)
{
int value = 5;
int *int_val = &value;
printf ("The value we have is %d\n", *int_val);
return 0;
}
and compiled it to the following asm using: gcc -o pointer.s -fno-asynchronous-unwind-tables pointer.c
:[1][2] 并使用以下命令将其编译为以下asm:
gcc -o pointer.s -fno-asynchronous-unwind-tables pointer.c
:[1] [2]
.file "pointer.c"
.section .rodata
.LC0:
.string "The value we have is %d\n"
.text
.globl main
.type main, @function
main:
;------- function prologue
pushq %rbp
movq %rsp, %rbp
;---------------------------------
subq $32, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
;----------------------------------
movl $5, -20(%rbp) ; This is where the value 5 is stored in `value` (automatic allocation)
;----------------------------------
leaq -20(%rbp), %rax ;; (GUESS) If I have understood correctly, this is where the address of `value` is
;; extracted, and stored into %rax
;----------------------------------
movq %rax, -16(%rbp) ;;
movq -16(%rbp), %rax ;; Why do I have two times the same instructions, with reversed operands???
;----------------------------------
movl (%rax), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
;----------------------------------
movl $0, %eax
movq -8(%rbp), %rdx
xorq %fs:40, %rdx
je .L3
call __stack_chk_fail
.L3:
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1"
.section .note.GNU-stack,"",@progbits
My issue is that I don't understand why it contains the instruction movq
two times, with reversed operands. 我的问题是我不明白为什么它包含指令
movq
两次,反向操作数。 Could someone explain it to me? 有人可以向我解释一下吗?
[1]: I want to avoid having my asm code interspersed with cfi directives when I don't need them at all. [1]:当我根本不需要它时,我想避免让我的asm代码穿插cfi指令。
[2]: My environment is Ubuntu 14.10
, gcc 4.9.1
(modified by ubuntu), and Gnu assembler (GNU Binutils for Ubuntu) 2.24.90.20141014
, configured to target x86_64-linux-gnu
[2]:我的环境是
Ubuntu 14.10
, gcc 4.9.1
(由ubuntu修改)和Gnu assembler (GNU Binutils for Ubuntu) 2.24.90.20141014
,配置为目标x86_64-linux-gnu
Maybe it will be clearer if you reorganize your blocks: 如果重组你的块,也许会更清楚:
;----------------------------------
leaq -20(%rbp), %rax ; &value
movq %rax, -16(%rbp) ; int_val
;----------------------------------
movq -16(%rbp), %rax ; int_val
movl (%rax), %eax ; *int_val
movl %eax, %esi ; printf-argument
movl $.LC0, %edi ; printf-argument (format-string)
movl $0, %eax ; no floating-point numbers
call printf
;----------------------------------
The first block performs int *int_val = &value;
第一个块执行
int *int_val = &value;
, the second block performs printf ...
. ,第二个块执行
printf ...
Without optimization, the blocks are independent. 没有优化,块是独立的。
Since you're not doing any optimization, gcc creates very simple-minded code that does each statement in the program one at a time without looking at any other statement. 由于您没有进行任何优化,因此gcc创建了非常简单的代码,可以一次一个地执行程序中的每个语句,而无需查看任何其他语句。 So in your example, it stores a value into the variable
int_val
, and then the very next instruction reads that variable again as part of the next statement. 因此,在您的示例中,它将值存储到变量
int_val
,然后下一条指令再次读取该变量作为下一个语句的一部分。 In both cases, it is using %rax
as the temporary to hold value, as that's the first register generally used for things. 在这两种情况下,它都使用
%rax
作为保留值的临时值,因为这是通常用于事物的第一个寄存器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.