[bits 32]
global _start
section .data
str_hello db "HelloWorld", 0xa
str_hello_length db $-str_hello
section .text
_start:
mov ebx, 1 ; stdout file descriptor
mov ecx, str_hello ; pointer to string of characters that will be displayed
mov edx, [str_hello_length] ; count outputs Relative addressing
mov eax, 4 ; sys_write
int 0x80 ; linux kernel system call
mov ebx, 0 ; exit status zero
mov eax, 1 ; sys_exit
int 0x80 ; linux kernel system call
The fundamental thing here is that I need to have the length of the hello string to pass to linux's sys_write system call. Now, I'm well aware that I can just use EQU and it'll work fine, but I'm really trying to understand what's going on here.
So, basically when I use EQU it loads the value and that's fine.
str_hello_length equ $-str_hello
...
...
mov edx, str_hello_length
However, if I use this line with DB
str_hello_length db $-str_hello
...
...
mov edx, [str_hello_length] ; of course, without the brackets it'll load the address, which I don't want. I want the value stored at that address
instead of loading the value at that address like I expect it to, the assembler outputs RIP-Relative Addressing, as shown in the gdb debugger and I'm simply just wondering why.
mov 0x6000e5(%rip),%edx # 0xa001a5
Now, I've tried using the eax register instead(and then moving eax to edx), but then I get a different problem. I end up getting a segmentation fault as noted in gdb:
movabs 0x4b8c289006000e5,%eax
so apparently, different registers produce different code. I guess I need to truncate the upper 32-bits somehow , but I don't know how to do that.
Though did kind of found a 'solution' and it goes like this: load eax with str_hello_length's address and then load the contents of address that eax points to and everything is hunky dory.
mov eax, str_hello_length
mov edx, [eax] ; count
; gdb disassembly
mov $0x6000e5,%eax
mov (%rax),%edx
apparently trying to indirectly load a value from a mem address produces different code? I don't really know.
I just need help in understanding the syntax and operations of these instructions, so I can better understand why how to load effective addresses. Yeah, I guess I could've just switched to EQU and be on my merry way, but I really feel I can't go on until I understand what's going on with the DB declaration and loading from it's address.
rip
andrax
do not exist in 32 bit mode. So the problem is that you believe you are generating code for 32 bit, where in reality you have 64 bit code. That said, producingrip
relative memory addresses is the default in x86_64, even if you don't explicitly staterip
in the square brackets. – Gunther Piezgcc -m32
for linking, or the appropriate ld flag (-m elf_i386
). – mirabilos