问题描述
0x0000000000400553 <main+59>: mov -0x4(%rbp),%eax
0x0000000000400556 <main+62>: cltq
0x0000000000400558 <main+64>: shl $0x3,%rax
0x000000000040055c <main+68>: mov %rax,%rdx
实际上我的程序很简单:
In fact my programe is as simple as :
5 int main(int argc, char *argv[]) {
6 int i = 0;
7 while(environ[i]) {
8 printf("%s\n", environ[i++]);
9 }
10 return 0;
但是程序集输出相当长:
But the assembly output is pretty long:
Dump of assembler code for function main:
0x0000000000400518 <main+0>: push %rbp
0x0000000000400519 <main+1>: mov %rsp,%rbp
0x000000000040051c <main+4>: sub $0x20,%rsp
0x0000000000400520 <main+8>: mov %edi,-0x14(%rbp)
0x0000000000400523 <main+11>: mov %rsi,-0x20(%rbp)
0x0000000000400527 <main+15>: movl $0x0,-0x4(%rbp)
0x000000000040052e <main+22>: jmp 0x400553 <main+59>
0x0000000000400530 <main+24>: mov -0x4(%rbp),%eax
0x0000000000400533 <main+27>: cltq
0x0000000000400535 <main+29>: shl $0x3,%rax
0x0000000000400539 <main+33>: mov %rax,%rdx
0x000000000040053c <main+36>: mov 0x2003e5(%rip),%rax # 0x600928 <environ@@GLIBC_2.2.5>
0x0000000000400543 <main+43>: lea (%rdx,%rax,1),%rax
0x0000000000400547 <main+47>: mov (%rax),%rdi
0x000000000040054a <main+50>: addl $0x1,-0x4(%rbp)
0x000000000040054e <main+54>: callq 0x400418 <puts@plt>
0x0000000000400553 <main+59>: mov -0x4(%rbp),%eax
0x0000000000400556 <main+62>: cltq
0x0000000000400558 <main+64>: shl $0x3,%rax
0x000000000040055c <main+68>: mov %rax,%rdx
0x000000000040055f <main+71>: mov 0x2003c2(%rip),%rax # 0x600928 <environ@@GLIBC_2.2.5>
0x0000000000400566 <main+78>: lea (%rdx,%rax,1),%rax
0x000000000040056a <main+82>: mov (%rax),%rax
0x000000000040056d <main+85>: test %rax,%rax
0x0000000000400570 <main+88>: jne 0x400530 <main+24>
0x0000000000400572 <main+90>: mov $0x0,%eax
0x0000000000400577 <main+95>: leaveq
0x0000000000400578 <main+96>: retq
End of assembler dump.
我不明白的是这个障碍:
What I don't understand is this block:
0x000000000040052e <main+22>: jmp 0x400553 <main+59>
0x0000000000400530 <main+24>: mov -0x4(%rbp),%eax
0x0000000000400533 <main+27>: cltq
0x0000000000400535 <main+29>: shl $0x3,%rax
0x0000000000400539 <main+33>: mov %rax,%rdx
0x000000000040053c <main+36>: mov 0x2003e5(%rip),%rax # 0x600928 <environ@@GLIBC_2.2.5>
0x0000000000400543 <main+43>: lea (%rdx,%rax,1),%rax
0x0000000000400547 <main+47>: mov (%rax),%rdi
0x000000000040054a <main+50>: addl $0x1,-0x4(%rbp)
0x000000000040054e <main+54>: callq 0x400418 <puts@plt>
0x0000000000400553 <main+59>: mov -0x4(%rbp),%eax
0x0000000000400556 <main+62>: cltq
0x0000000000400558 <main+64>: shl $0x3,%rax
0x000000000040055c <main+68>: mov %rax,%rdx
0x000000000040055f <main+71>: mov 0x2003c2(%rip),%rax # 0x600928 <environ@@GLIBC_2.2.5>
0x0000000000400566 <main+78>: lea (%rdx,%rax,1),%rax
0x000000000040056a <main+82>: mov (%rax),%rax
0x000000000040056d <main+85>: test %rax,%rax
0x0000000000400570 <main+88>: jne 0x400530 <main+24>
推荐答案
助记符
cltq
是英特尔cdqe
的gas
助记符,如以下文档所示: https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html
cltq
is the gas
mnemonic for Intel's cdqe
as documented at: https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html
助记符是:
- 将长整数转换为四进制(
cltq
):AT& T样式 - 将双倍转换为四倍扩展(
cdqe
):Intel
- Convert Long To Quad (
cltq
): AT&T-style - Convert Double to Quad Extend (
cdqe
): Intel
术语:
- quad(又称四字)== 8个字节
- long(AT& T)==双字(Intel)== 4字节
这是其GAS名称与Intel版本非常不同的少数指令之一. as
接受任何助记符,但是像NASM这样的Intel语法汇编程序只能接受Intel名称.
This is one of the few instructions whose GAS name is very different from the Intel version. as
accepts either mnemonic, but Intel-syntax assemblers like NASM may only accept the Intel names.
效果
该符号将4个字节扩展为8个字节,以2的补码表示对于:
It sign extends 4 bytes into 8 bytes, which in 2's complement means that for:
- 负数,高4个字节的位必须设置为1
- 正数,必须将其设置为0
在C语言中,通常表示从带符号的int
到long
的转换.
In C, that usually represents a cast from signed int
to long
.
示例:
mov $0123456700000001, %rax # eax=1, high bytes of rax=garbage
cltq
# %rax == $0000 0000 0000 0001
mov $-1, %eax # %rax = 0000 0000 FFFF FFFF
cltq
# %rax == $FFFF FFFF FFFF FFFF == qword $-1
此指令仅适用于64位.
This instruction is only available on 64-bits.
还请考虑以下说明:
-
CWDE
(AT& TCWTL
),CBW
(AT& TCBTW
):CDQE
的较小版本,也以32位出现 -
CQO
系列,其符号将RAX
扩展到RDX:RAX
-
MOVSX
系列,其符号都可以扩展和移动: movsbl指令做什么?/a>
CWDE
(AT&TCWTL
),CBW
(AT&TCBTW
): smaller versions ofCDQE
, also present in 32-bitCQO
family, which sign extendsRAX
intoRDX:RAX
MOVSX
family, which both sign extends and moves: what does movsbl instruction do?
GitHub上带有断言的最小可运行示例:
Minimal runnable examples on GitHub with assertions:
C示例
GCC 4.9.3发出它:
GCC 4.9.3 emits it:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i = strtol(argv[1], (char **)NULL, 16);;
long int l = i;
printf("%lx\n", l);
}
编译和反汇编:
gcc -ggdb3 -std=c99 -O0 a.c
objdump -S a.out
包含:
int main(int argc, char **argv) {
...
long int l2 = i;
400545: 8b 45 fc mov -0x4(%rbp),%eax
400548: 48 98 cltq
40054a: 48 89 45 f0 mov %rax,-0x10(%rbp)
,其行为是:
$ ./a.out 0x80000000
ffffffff80000000
$ ./a.out 0x40000000
40000000
这篇关于cltq在组装中做什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!