[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
Фундаментальная вещь здесь заключается в том, что мне нужно иметь длину строки приветствия для передачи в системный вызов linux sys_write. Теперь я хорошо знаю, что могу просто использовать EQU, и он будет работать нормально, но я действительно пытаюсь понять, что здесь происходит.
Итак, в основном, когда я использую EQU, он загружает значение, и это нормально.
str_hello_length equ $-str_hello
...
...
mov edx, str_hello_length
Однако, если я использую эту строку с БД
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
вместо загрузки значения по этому адресу, как я ожидал, ассемблер выводит RIP-Relative Addressing, как показано в отладчике gdb, и мне просто интересно, почему.
mov 0x6000e5(%rip),%edx # 0xa001a5
Теперь я попытался использовать вместо этого регистр eax (а затем переместить eax в edx), но затем у меня возникла другая проблема. Я получаю ошибку сегментации, как указано в GDB:
movabs 0x4b8c289006000e5,%eax
так что, очевидно, разные регистры производят разный код. Думаю, мне нужно каким-то образом обрезать верхние 32-битные символы, но я не знаю, как это сделать.
Хотя вроде как нашел «решение» и оно выглядит так:
загрузите eax с адресом str_hello_length, а затем загрузите содержимое адреса, на который указывает eax, и все будет просто ужасно.
mov eax, str_hello_length
mov edx, [eax] ; count
; gdb disassembly
mov $0x6000e5,%eax
mov (%rax),%edx
очевидно, попытка косвенной загрузки значения из адреса mem дает другой код? Я действительно не знаю.
Мне просто нужна помощь в понимании синтаксиса и операций этих инструкций, чтобы я мог лучше понять, почему, как загружать эффективные адреса. Да, я полагаю, что мог бы просто переключиться на EQU и быть на моем веселом пути, но я действительно чувствую, что не могу продолжать, пока не пойму, что происходит с объявлением DB и загрузкой с его адреса.