1

Here's is a simple program:

%include 'utils/system.inc'

section .data
  first:  db 'First is bigger', 0xA,0
  second: db 'Second is bigger', 0xA,0
  a:      db 18
  b:      db 20
section .text
global start
start:
 mov rax, [a wrt rip]
 mov rbx, [b wrt rip]
 cmp rax, rbx
 jle else                        
 mov rsi, qword first
 mov rdx, 0x10
 jmp end
else:
 mov rsi, qword second
 mov rdx, 0x11
end:
 xor rax, rax
 xor rbx, rbx
 mov rax, 0x2000004
 mov rdi, stdout
 syscall

 xor rdi, rdi
 mov rax, 0x2000001
 syscall 

The problem is that variable a contains a different value than 18. Here's what lldb shows me:

(lldb) p a
(void *) $0 = 0x0000000000001412
(lldb) p b
(void *) $1 = 0x0000000000000014
(lldb) p --format decimal a

Any ideas what's going on? I know that if I declare a as dq, it will be alright, but I want to understand why it's happening.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
nullbyte
  • 1,178
  • 8
  • 16
  • 2
    Because you when you do `mov rax, [a wrt rip]` it moves the 8 bytes starting at label `a` and moves that into RAX. You have defined `a` and `b` as bytes and not 8 byte quadwords. You are effectively reading more bytes than needed. For instance 18=0x12 and 20=0x14. When read little endian you'd get 0x1412 in the lower 16 bits of the register which is what you got here. – Michael Petch Feb 13 '18 at 06:17
  • 1
    If you want to read a single byte you can do `mov al, [a wrt rip]` and `mov bl, [b wrt rip]` and then compare al and bl. If you want to read a byte and have it sign extended through an entire 64-bit register you can do `movsx rax, byte [a wrt rip]` and `movsx rbx, byte [b wrt rip]` and then do the comparison on the 64-bit registers as you did before. – Michael Petch Feb 13 '18 at 06:25
  • 1
    Oh, that does make sense to me now. Thank you! – nullbyte Feb 13 '18 at 06:26

0 Answers0