Предположим, что у меня есть целое число в регистре, как я могу его распечатать? Вы можете показать простой пример кода?
Я уже знаю, как печатать строку, такую как "привет, мир".
Я разрабатываю Linux.
Предположим, что у меня есть целое число в регистре, как я могу его распечатать? Вы можете показать простой пример кода?
Я уже знаю, как печатать строку, такую как "привет, мир".
Я разрабатываю Linux.
Если вы уже работаете в Linux, вам не нужно делать преобразование самостоятельно. Просто используйте printf:
;
; assemble and link with:
; nasm -f elf printf-test.asm && gcc -m32 -o printf-test printf-test.o
;
section .text
global main
extern printf
main:
  mov eax, 0xDEADBEEF
  push eax
  push message
  call printf
  add esp, 8
  ret
message db "Register = %08X", 10, 0
Обратите внимание, что printf использует соглашение о вызове cdecl, поэтому нам нужно восстановить указатель стека после этого, то есть добавить 4 байта на каждый переданный функции.
Вы должны преобразовать это в строку; если вы говорите о шестнадцатеричных числах, это довольно просто. Любое число можно представить так:
0xa31f = 0xf * 16^0 + 0x1 * 16^1 + 3 * 16^2 + 0xa * 16^3
 Поэтому, когда у вас есть это число, вы должны разделить его, как я показал, затем преобразовать каждый "раздел" в его эквивалент ASCII. 
 Получение четырех частей легко сделать с помощью некоторой немного магии, в частности, с помощью сдвига вправо, чтобы переместить интересующую нас часть в первые четыре бита, а затем результат с 0xf, чтобы изолировать его от остальных. Вот что я имею в виду (так что мы хотим взять 3):
0xa31f -> shift right by 8 = 0x00a3 -> AND with 0xf = 0x0003
 Теперь, когда у нас есть одно число, мы должны преобразовать его в значение ASCII. Если число меньше или равно 9, мы можем просто добавить 0 значение ASCII (0x30), если оно больше 9, мы должны использовать значение ASCII (0x61). 
 Вот оно, теперь мы просто должны его кодировать:
    mov si, ???         ; si points to the target buffer
    mov ax, 0a31fh      ; ax contains the number we want to convert
    mov bx, ax          ; store a copy in bx
    xor dx, dx          ; dx will contain the result
    mov cx, 3           ; cx our counter
convert_loop:
    mov ax, bx          ; load the number into ax
    and ax, 0fh         ; we want the first 4 bits
    cmp ax, 9h          ; check what we should add
    ja  greater_than_9
    add ax, 30h         ; 0x30 ('0')
    jmp converted
greater_than_9:
    add ax, 61h         ; or 0x61 ('a')
converted:
    xchg    al, ah      ; put a null terminator after it
    mov [si], ax        ; (will be overwritten unless this
    inc si              ; is the last one)
    shr bx, 4           ; get the next part
    dec cx              ; one less to do
    jnz convert_loop
    sub di, 4           ; di still points to the target buffer
PS: я знаю, что это 16-битный код, но я все еще использую старый TASM: P
PPS: это синтаксис Intel, однако преобразование в синтаксис AT & T не сложно, посмотрите здесь.
Linux x86-64 с printf
main.asm
default rel            ; make [rel format] the default, you always want this.
extern printf, exit    ; NASM requires declarations of external symbols, unlike GAS
section .rodata
    format db "%#x", 10, 0   ; C 0-terminated string: "%#x\n" 
section .text
global main
main:
    sub   rsp, 8             ; re-align the stack to 16 before calling another function
    ; Call printf.
    mov   esi, 0x12345678    ; "%x" takes a 32-bit unsigned int
    lea   rdi, [rel format]
    xor   eax, eax           ; AL=0  no FP args in XMM regs
    call  printf
    ; Return from main.
    xor   eax, eax
    add   rsp, 8
    ret
Затем:
nasm -f elf64 -o main.o main.asm
gcc -no-pie -o main.out main.o
./main.out
Выход:
0x12345678
Заметки:
sub rsp, 8: Как написать программу Hello World на ассемблере для 64-битной Mac OS X с использованием printf?xor eax, eax: почему% eax обнуляется перед вызовом printf? -no-pie: обычный call printf не работает в исполняемом файле PIE (-pie), компоновщик автоматически генерирует заглушку PLT для исполняемых файлов старого стиля. Ваши варианты:
 call printf wrt..plt для вызова через PLT, как традиционный call printf
 call [rel printf wrt..got] чтобы вообще не использовать PLT, например, gcc -fno-plt.
 Как и синтаксический call *[email protected](%rip) GAS call *[email protected](%rip).
 Любой из них также подходит для исполняемого файла, не являющегося -pie, и не вызывает никакой неэффективности, если вы не статически связываете libc. В этом случае call printf может разрешить call rel32 непосредственно в libc, потому что смещение от вашего кода к функции libc будет известно во время статического связывания.
Смотрите также: Невозможно вызвать функцию стандартной библиотеки C в 64-битном Linux из кода сборки (yasm)
Если вам нужен шестнадцатеричный код без библиотеки C: печать шестнадцатеричных цифр с помощью Assembly
Протестировано на Ubuntu 18.10, NASM 2.13.03.
Это зависит от архитектуры/среды, которую вы используете.
Например, если я хочу отображать число в linux, код ASM будет отличаться от кода, который я буду использовать в Windows.
Edit:
Вы можете обратиться к ЭТО для примера преобразования.
Я относительно новичок в сборке, и это, очевидно, не лучшее решение, но он работает. Основной функцией является _iprint, она сначала проверяет, число в eax отрицательно и печатает знак минус, если это так, чем это происходит путем печати отдельных номеров путем вызова функции _dprint для каждую цифру. Идея следующая: если мы имеем 512, то она равна: 512 = (5 * 10 + 1) * 10 + 2 = Q * 10 + R, поэтому мы можем найти последнюю цифру числа, разделив ее на 10 и получая напоминание R, но если мы сделаем это в цикле, то цифры будут в обратный порядок, поэтому мы используем стек для их нажатия, а затем, когда записывая их в stdout, они выходят в правильном порядке.
; Build        : nasm -f elf -o baz.o baz.asm
;                ld -m elf_i386 -o baz baz.o
section .bss
c: resb 1 ; character buffer
section .data
section .text
; writes an ascii character from eax to stdout
_cprint:
    pushad        ; push registers
    mov [c], eax  ; store ascii value at c
    mov eax, 0x04 ; sys_write
    mov ebx, 1    ; stdout
    mov ecx, c    ; copy c to ecx
    mov edx, 1    ; one character
    int 0x80      ; syscall
    popad         ; pop registers
    ret           ; bye
; writes a digit stored in eax to stdout 
_dprint:
    pushad        ; push registers
    add eax, '0'  ; get digit ascii code
    mov [c], eax  ; store it at c
    mov eax, 0x04 ; sys_write
    mov ebx, 1    ; stdout
    mov ecx, c    ; pass the address of c to ecx
    mov edx, 1    ; one character
    int 0x80      ; syscall
    popad         ; pop registers
    ret           ; bye
; now lets try to write a function which will write an integer
; number stored in eax in decimal at stdout
_iprint:
    pushad       ; push registers
    cmp eax, 0   ; check if eax is negative
    jge Pos      ; if not proceed in the usual manner
    push eax     ; store eax
    mov eax, '-' ; print minus sign
    call _cprint ; call character printing function 
    pop eax      ; restore eax
    neg eax      ; make eax positive
Pos:
    mov ebx, 10 ; base
    mov ecx, 1  ; number of digits counter
Cycle1:
    mov edx, 0  ; set edx to zero before dividing otherwise the
    ; program gives an error: SIGFPE arithmetic exception
    div ebx     ; divide eax with ebx now eax holds the
    ; quotent and edx the reminder
    push edx    ; digits we have to write are in reverse order
    cmp eax, 0  ; exit loop condition
    jz EndLoop1 ; we are done
    inc ecx     ; increment number of digits counter
    jmp Cycle1  ; loop back
EndLoop1:
; write the integer digits by poping them out from the stack
Cycle2:
    pop eax      ; pop up the digits we have stored
    call _dprint ; and print them to stdout
    dec ecx      ; decrement number of digits counter
    jz EndLoop2  ; if it zero we are done
    jmp Cycle2   ; loop back
EndLoop2:   
    popad ; pop registers
    ret   ; bye
global _start
_start:
    nop           ; gdb break point
    mov eax, -345 ;
    call _iprint  ; 
    mov eax, 0x01 ; sys_exit
    mov ebx, 0    ; error code
    int 0x80      ; край
Поскольку вы не сказали о представлении чисел, я написал следующий код для числа без знака с любой базой (конечно, не слишком большой), чтобы вы могли использовать его:
BITS 32
global _start
section .text
_start:
mov eax, 762002099 ; unsigned number to print
mov ebx, 36        ; base to represent the number, do not set it too big
call print
;exit
mov eax, 1
xor ebx, ebx
int 0x80
print:
mov ecx, esp
sub esp, 36   ; reserve space for the number string, for base-2 it takes 33 bytes with new line, aligned by 4 bytes it takes 36 bytes.
mov edi, 1
dec ecx
mov [ecx], byte 10
print_loop:
xor edx, edx
div ebx
cmp dl, 9     ; if reminder>9 go to use_letter
jg use_letter
add dl, '0'
jmp after_use_letter
use_letter:
add dl, 'W'   ; letters from 'a' to ... in ascii code
after_use_letter:
dec ecx
inc edi
mov [ecx],dl
test eax, eax
jnz print_loop
; system call to print, ecx is a pointer on the string
mov eax, 4    ; system call number (sys_write)
mov ebx, 1    ; file descriptor (stdout)
mov edx, edi  ; length of the string
int 0x80
add esp, 36   ; release space for the number string
ret
 Он не оптимизирован для чисел с основанием степени два и не использует printf из libc.
 Функция print выводит номер с новой строки. Числовая строка формируется в стеке. Компилировать по насм.
Выход:
clockz