Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does cltq do in assembly?

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> 
like image 960
R__ Avatar asked Jul 02 '11 04:07

R__


People also ask

What does CLTQ mean in assembly?

cltq is the AT&T mnemonic for CDQE, which sign-extends EAX into RAX. It's a short-form of movslq %eax, %rax , saving code bytes. It exists because of how x86-64 evolved from 8086 to 386 to AMD64. It copies the sign bit of EAX to all the upper bits of the wider register, because that's how 2's complement works.

What does RETQ do in x86?

The retq instruction pops the return address from the stack into the destination %rip , thus resuming at the saved return address.

What does Movslq mean in assembly?

MOVSLQ is move and sign-extend a value from a 32-bit source to a 64-bit destination. I understand this like this.

What does CLT do in assembly?

ASSEMBLY & INSTALLATION A great deal of leeway in design and statics is made possible by the combination of CLT as the load-bearing, stiffening panel material with glulam as supports and beams. The architecture in the interior can also be designed in a versatile and lively way.


2 Answers

Mnemonic

cltq is the gas mnemonic for Intel's cdqe as documented at: https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html

The mnemonics are:

  • Convert Long To Quad (cltq): AT&T-style
  • Convert Double to Quad Extend (cdqe): Intel

Terminology:

  • quad (aka quad-word) == 8 bytes
  • long (AT&T) == double-word (Intel) == 4 bytes

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.

Effect

It sign extends 4 bytes into 8 bytes, which in 2's complement means that for:

  • negative numbers, the bits of the upper 4 bytes must set to 1
  • positive numbers, they must be set to 0

In C, that usually represents a cast from signed int to long.

Example:

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 

This instruction is only available on 64-bits.

Also consider the following instructions:

  • CWDE (AT&T CWTL), CBW (AT&T CBTW): smaller versions of CDQE, also present in 32-bit
  • CQO family, which sign extends RAX into RDX:RAX
  • MOVSX family, which both sign extends and moves: what does movsbl instruction do?

Minimal runnable examples on GitHub with assertions:

  • CWDE and CWTL
  • CDQE and CLTQ

C example

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); } 

Compile and disassemble:

gcc -ggdb3 -std=c99 -O0 a.c objdump -S a.out 

contains:

    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) 

and the behavior is:

$ ./a.out 0x80000000 ffffffff80000000 $ ./a.out 0x40000000 40000000 

cltq promotes an int to an int64. shl 3, %rax makes an offset to a 64-bit pointer (multiplies whatever is in rax by 8). what the code is doing is looping through a list of pointers to environment variables. when it finds a value of zero, that's the end, and it drops out of the loop.

Here is a visual on how Linux stores the environment variables in RAM, above the stack. You'll see the pointers starting at 0xbffff75c; that points to 0xbffff893, "TERM=rxvt".

jcomeau@intrepid:/tmp$ gdb test GNU gdb (GDB) 7.2-debian Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /tmp/test...(no debugging symbols found)...done. (gdb) break main Breakpoint 1 at 0x80483e7 (gdb) run Starting program: /tmp/test   Breakpoint 1, 0x080483e7 in main () (gdb) info reg eax            0xbffff754   -1073744044 ecx            0xe88ed1c    243854620 edx            0x1  1 ebx            0xb7fc5ff4   -1208197132 esp            0xbffff6a8   0xbffff6a8 ebp            0xbffff6a8   0xbffff6a8 esi            0x0  0 edi            0x0  0 eip            0x80483e7    0x80483e7 <main+3> eflags         0x200246 [ PF ZF IF ID ] cs             0x73 115 ss             0x7b 123 ds             0x7b 123 es             0x7b 123 fs             0x0  0 gs             0x33 51 (gdb) x/160x 0xbffff6a8 0xbffff6a8: 0xbffff728  0xb7e86e46  0x00000001  0xbffff754 0xbffff6b8: 0xbffff75c  0xb7fe2940  0xb7ff7351  0xffffffff 0xbffff6c8: 0xb7ffeff4  0x08048254  0x00000001  0xbffff710 0xbffff6d8: 0xb7ff0976  0xb7fffac0  0xb7fe2c38  0xb7fc5ff4 0xbffff6e8: 0x00000000  0x00000000  0xbffff728  0x21b99b0c 0xbffff6f8: 0x0e88ed1c  0x00000000  0x00000000  0x00000000 0xbffff708: 0x00000001  0x08048330  0x00000000  0xb7ff64f0 0xbffff718: 0xb7e86d6b  0xb7ffeff4  0x00000001  0x08048330 0xbffff728: 0x00000000  0x08048351  0x080483e4  0x00000001 0xbffff738: 0xbffff754  0x08048440  0x08048430  0xb7ff12f0 0xbffff748: 0xbffff74c  0xb7fff908  0x00000001  0xbffff889 0xbffff758: 0x00000000  0xbffff893  0xbffff89d  0xbffff8ad 0xbffff768: 0xbffff8fd  0xbffff90c  0xbffff91c  0xbffff92d 0xbffff778: 0xbffff93a  0xbffff94d  0xbffff97a  0xbffffe6a 0xbffff788: 0xbffffe75  0xbffffef7  0xbfffff0e  0xbfffff1d 0xbffff798: 0xbfffff26  0xbfffff30  0xbfffff41  0xbfffff6a 0xbffff7a8: 0xbfffff73  0xbfffff8a  0xbfffff9d  0xbfffffa5 0xbffff7b8: 0xbfffffbc  0xbfffffcc  0xbfffffdf  0x00000000 0xbffff7c8: 0x00000020  0xffffe420  0x00000021  0xffffe000 0xbffff7d8: 0x00000010  0x078bfbff  0x00000006  0x00001000 0xbffff7e8: 0x00000011  0x00000064  0x00000003  0x08048034 0xbffff7f8: 0x00000004  0x00000020  0x00000005  0x00000008 0xbffff808: 0x00000007  0xb7fe3000  0x00000008  0x00000000 ---Type <return> to continue, or q <return> to quit--- 0xbffff818: 0x00000009  0x08048330  0x0000000b  0x000003e8 0xbffff828: 0x0000000c  0x000003e8  0x0000000d  0x000003e8 0xbffff838: 0x0000000e  0x000003e8  0x00000017  0x00000000 0xbffff848: 0x00000019  0xbffff86b  0x0000001f  0xbffffff2 0xbffff858: 0x0000000f  0xbffff87b  0x00000000  0x00000000 0xbffff868: 0x50000000  0x7d410985  0x1539ef2a  0x7a3f5e9a 0xbffff878: 0x6964fe17  0x00363836  0x00000000  0x00000000 0xbffff888: 0x6d742f00  0x65742f70  0x54007473  0x3d4d5245 0xbffff898: 0x74767872  0x45485300  0x2f3d4c4c  0x2f6e6962 0xbffff8a8: 0x68736162  0x47445800  0x5345535f  0x4e4f4953 0xbffff8b8: 0x4f4f435f  0x3d45494b  0x37303534  0x66656135 0xbffff8c8: 0x32353131  0x63346334  0x30393436  0x35386331 0xbffff8d8: 0x39346134  0x37316135  0x3033312d  0x31383339 0xbffff8e8: 0x2e303736  0x31303832  0x382d3033  0x33323731 0xbffff8f8: 0x39373936  0x53494800  0x5a495354  0x30313d45 0xbffff908: 0x00303030  0x48535548  0x49474f4c  0x41463d4e 0xbffff918: 0x0045534c  0x444e4957  0x4449574f  0x3833383d (gdb) x/20s 0xbffff888 0xbffff888:  "" 0xbffff889:  "/tmp/test" 0xbffff893:  "TERM=rxvt" 0xbffff89d:  "SHELL=/bin/bash" 0xbffff8ad:  "XDG_SESSION_COOKIE=45075aef11524c4c64901c854a495a17-1309381670.280130-817236979" 0xbffff8fd:  "HISTSIZE=10000" 0xbffff90c:  "HUSHLOGIN=FALSE" 0xbffff91c:  "WINDOWID=8388614" 0xbffff92d:  "USER=jcomeau" 0xbffff93a:  "HISTFILESIZE=10000" 0xbffff94d:  "LD_LIBRARY_PATH=/usr/src/jet/lib/x86/shared:" 0xbffff97a:  "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31"... 0xbffffa42:  ":*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.d"... 0xbffffb0a:  "eb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35"... 0xbffffbd2:  ":*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=---Type <return> to continue, or q <return> to quit--- 01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4"... 0xbffffc9a:  "v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*."... 0xbffffd62:  "yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;3"... 0xbffffe2a:  "6:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:" 0xbffffe6a:  "COLUMNS=80" 0xbffffe75:  "PATH=/usr/src/jet/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/home/jcomeau:/home/jcomeau/bin:/home/jcomeau/src:/sbin:/usr/sbin:." (gdb) quit A debugging session is active.      Inferior 1 [process 10880] will be killed.  Quit anyway? (y or n) y 

Your compiler is apparently smart enough to optimize the simply-formatted printf to a puts. the fetching of the environment string, and the postincrement of i, are right there in the code. If you don't figure some of this out on your own you'll never really understand it. Just "be" the computer, and step through the loop, using the data I dumped out for you with gdb, and it should all become clear to you.

like image 45
jcomeau_ictx Avatar answered Sep 30 '22 22:09

jcomeau_ictx