理解这些汇编指令
Understanding these assembly instructions
我正在通过编写 C 程序和查看汇编输出来学习汇编。我在页面底部包含了 C 程序以使其更容易。我正在努力理解一行汇编:
cdqe
movzx eax, BYTE PTR [rbp-32+rax] <--- 这是在做什么?
movsx eax, al
所以我认为 cdqe 将 eax 扩展为 rax(64 位)。很明显,我要打印的字符串适合 al 寄存器,但我不明白 rbp-32+rax 到底发生了什么。有人可以为我解释一下吗?
.file "string_manip.c"
.intel_syntax noprefix
.section .rodata
.LC0:
.string "Hello"
.string ""
.zero 3
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 48
mov rax, QWORD PTR fs:40
mov QWORD PTR [rbp-8], rax
xor eax, eax
mov DWORD PTR [rbp-36], 0
mov eax, DWORD PTR .LC0[rip]
mov DWORD PTR [rbp-32], eax
movzx eax, WORD PTR .LC0[rip+4]
mov WORD PTR [rbp-28], ax
movzx eax, BYTE PTR .LC0[rip+6]
mov BYTE PTR [rbp-26], al
mov WORD PTR [rbp-25], 0
mov BYTE PTR [rbp-23], 0
mov DWORD PTR [rbp-36], 0
jmp .L2
.L3:
mov eax, DWORD PTR [rbp-36]
cdqe
movzx eax, BYTE PTR [rbp-32+rax] <--- what is this doing?
movsx eax, al
mov edi, eax
call putchar
add DWORD PTR [rbp-36], 1
.L2:
cmp DWORD PTR [rbp-36], 5
jle .L3
mov edi, 10
call putchar
mov eax, 0
mov rdx, QWORD PTR [rbp-8]
xor rdx, QWORD PTR fs:40
je .L5
call __stack_chk_fail
.L5:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits
#include <string.h>
#include <stdio.h>
int main()
{
int i = 0;
char array[10] = "Hello[=10=]";
for(i=0; i<6; i++)
printf("%c", array[i]);
printf("\n");
return 0;
}
只是计算其中一个字符的地址。
大概你的字符串从 rbp-32
开始,然后指令执行 C 等效的 ch = string[rax]
.
我猜这是未优化的代码,因此编译器做了一些并不真正需要的额外符号扩展和零扩展。
我正在通过编写 C 程序和查看汇编输出来学习汇编。我在页面底部包含了 C 程序以使其更容易。我正在努力理解一行汇编:
cdqe
movzx eax, BYTE PTR [rbp-32+rax] <--- 这是在做什么?
movsx eax, al
所以我认为 cdqe 将 eax 扩展为 rax(64 位)。很明显,我要打印的字符串适合 al 寄存器,但我不明白 rbp-32+rax 到底发生了什么。有人可以为我解释一下吗?
.file "string_manip.c"
.intel_syntax noprefix
.section .rodata
.LC0:
.string "Hello"
.string ""
.zero 3
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 48
mov rax, QWORD PTR fs:40
mov QWORD PTR [rbp-8], rax
xor eax, eax
mov DWORD PTR [rbp-36], 0
mov eax, DWORD PTR .LC0[rip]
mov DWORD PTR [rbp-32], eax
movzx eax, WORD PTR .LC0[rip+4]
mov WORD PTR [rbp-28], ax
movzx eax, BYTE PTR .LC0[rip+6]
mov BYTE PTR [rbp-26], al
mov WORD PTR [rbp-25], 0
mov BYTE PTR [rbp-23], 0
mov DWORD PTR [rbp-36], 0
jmp .L2
.L3:
mov eax, DWORD PTR [rbp-36]
cdqe
movzx eax, BYTE PTR [rbp-32+rax] <--- what is this doing?
movsx eax, al
mov edi, eax
call putchar
add DWORD PTR [rbp-36], 1
.L2:
cmp DWORD PTR [rbp-36], 5
jle .L3
mov edi, 10
call putchar
mov eax, 0
mov rdx, QWORD PTR [rbp-8]
xor rdx, QWORD PTR fs:40
je .L5
call __stack_chk_fail
.L5:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits
#include <string.h>
#include <stdio.h>
int main()
{
int i = 0;
char array[10] = "Hello[=10=]";
for(i=0; i<6; i++)
printf("%c", array[i]);
printf("\n");
return 0;
}
只是计算其中一个字符的地址。
大概你的字符串从 rbp-32
开始,然后指令执行 C 等效的 ch = string[rax]
.
我猜这是未优化的代码,因此编译器做了一些并不真正需要的额外符号扩展和零扩展。