Вы должны сначала преобразовать его в текст. Вы можете пойти по простому маршруту и использовать, например, printf
из libc или, если вы хотите, напишите свою собственную утилиту преобразования.
Обновление: если вы хотите, чтобы код был позиционно независимым, проще использовать стек. Простое перемещение буфера в сегмент кода, поскольку код, на который вы ссылаетесь в комментариях, больше не работает, поскольку современные процессоры имеют сегменты кода только для чтения. Я обновил код для использования стека для временного хранения.
.text
call start
start:
movq $186, %rax # sys_gettid
syscall
movq %rax, %rdi
movq $10, %rsi
call print_number
#ret
mov $60, %rax # sys_exit
mov $0, %rdi
syscall
# rdi = number
# rsi = base
print_number:
sub $72, %rsp # alloc room for buffer on the stack, 8 more than needed
lea 64(%rsp), %rcx # 64(%rsp) == buffer end
movq %rdi, %rax # rax holds current number
1:
xorq %rdx, %rdx # clear rdx (div uses the 128-bit number in rdx:rax)
divq %rsi # divide by base, updating rax for the next iteration
# and giving us our digit in rdx (dl)
add $'0', %dl # turn into printable character
cmp $'9', %dl # handle digits > 10
jbe 2f
add $'A'-'0'-10, %dl # adjust number so A=10, B=11 ...
2:
sub $1, %rcx # subtract before adding character as we start from the end
mov %dl, (%rcx) # store character in string
and %rax, %rax # rax == 0?
jnz 1b # if not, then keep working
mov %rcx, %rsi # buf = address of last character stored
lea 64(%rsp), %rdx # calculate length by subtracting buffer end
sub %rcx, %rdx # from the buffer start
movq $1, %rax # sys_write
movq $1, %rdi # fd = STDOUT_FILENO
syscall
add $72, %rsp # adjust stack back
ret
Если, наоборот, вы хотите сохранить буфер в сегменте кода, это может быть сделано. Вы должны отметить страницу, где buffer
находится как доступная для записи, например, используя mprotect(2)
. Здесь сделано без проверки ошибок (и при условии sysconf(_SC_PAGE_SIZE) == 4096
) в сборке:
mov $10, %rax # sys_mprotect
lea buffer, %rdi # addr
and $-4096, %rdi # page align
mov $4096, %rsi # len
mov $7, %rdx #prot = PROT_READ|PROT_WRITE|PROT_EXEC
syscall
И теперь код должен работать, даже если буфер находится в сегменте кода. Кстати, я использую sys_exit в своем примере, потому что я тестирую его как отдельный файл с gcc x.s -nostdlib -ggdb -o x
.
Update2: чтобы использовать его при перемещении кода, используйте RIP-относительную адресацию. Измените bufferend
на bufferend(%rip)
.