Exemplos da aula 11 #20

Open
opened 2025-07-25 11:10:31 -03:00 by blau_araujo · 0 comments
Owner

Arquivo: demo.asm

%include "pbn-utils.asm"

%define BUF_SIZE 21
	
section .rodata
txt: db "abcdefghij", 0	; string com 10 caracteres + '\0'

section .bss
buf: resb BUF_SIZE	; espaço para 20 caracteres + '\0'
	
section .text
global _start
_start:
	mov rdi, buf	; endereço do buffer
	mov rsi, txt	; endereço da string
	call write_buf	; copia string e retona buffer em rsi
	call echo_str	; imprime string no endereço em rsi

_brev:
	mov rdi, buf	; endereço do buffer
	mov rsi, txt	; endereço da string
	call rev_buf	; inverte string e retorna buffer em rsi
	call echo_str	; imprime string no endereço em rsi

_pu64:
	mov rdi, 123456	; inteiro sem sinal 64 bits
	mov rsi, buf	; endereço do buffer
	call u64_to_str	; converte e retorna buffer em rsi
	call echo_str	; imprime string no endereço em rsi

_exit:
	mov rax, SYS_EXIT
	mov rdi, EXIT_OK
	syscall

Arquivo: pbn-utils.asm

%ifndef PBN_UTILS
%define PBN_UTILS
; ----------------------------------------------------------
%define SYS_WRITE 1
%define SYS_EXIT  60
; ----------------------------------------------------------
%define STDIN_FD 0
%define STDOUT_FD 1
%define STDERR_FD 2
; ----------------------------------------------------------
%define EXIT_OK   0
%define EXIT_FAIL 1
; ----------------------------------------------------------
%define EOL_CHAR  0x0a
; ----------------------------------------------------------
; Sub-rotinas...
; ----------------------------------------------------------
; - write_buf: copia string (rsi) para um buffer (rdi).
; - rev_buf  : inverte e salva string (rsi) em um buffer (rdi).
; - str_len  : obtém o tamanho de uma string (rsi).
; - print_str: imprime string (rsi)
; - print_eol: imprime quebra de linha.
; - echo_str : imprime string (rsi) com uma quebra de linha.
; - i64_count_digits: conta dígitos de um inteiro (base 10).
; - u64_to_str: converte inteiro sem sinal para string.
; ----------------------------------------------------------
write_buf:
; ----------------------------------------------------------
; Descrição: Copia string em rsi no buffer em rdi.
; Entradas:
;   rsi -> char *src (endereço da string)
;   rdi -> char *buf (endereço do buffer)
; Saída:
;   rsi -> char *buf (endereço do buffer)
; Aletra: rax, rcx, r8, rsi (retorno)
; ----------------------------------------------------------
	mov rcx, rsi		; rcx => endereço da string
	mov r8, rdi		; r8 => endereço do buffer
.write_loop:
	mov al, byte [rcx]	; copia byte em rsi para rax
	cmp al, 0		; o byte em rax é 0x00?
	je .done

	mov [r8], al		; copia bite de 'txt' em 'buf' 
	inc r8			; próximo espaço em 'buf'
	inc rcx			; próximo byte da string
	jmp .write_loop
.done:
	mov byte [r8], 0	; garante terminador nulo
	mov rsi, rdi		; rsi => endereço do buffer 
	ret
; ----------------------------------------------------------
rev_buf:
; ----------------------------------------------------------
; Descrição: Inverte string em rsi e salva no buffer em rdi.
; Entradas:
;   rdi -> char *buf (buffer para string invertida)	
;   rsi -> char *str (endereço da string)
; Saída:
;   rsi -> char *buf (endereço do buffer)
; Aletra: rax, rcx, r8, rsi (retorno)
; Depende de str_len!
; ----------------------------------------------------------
	call str_len		; retorna tamanho da string em rax
	mov r8, rdi		; r8 => endereço do buffer
	mov rcx, rsi		; rcx => endereço da string
	add rcx, rax		; rcx => terminador da string
	dec rcx			; rcx => último caractere
.write_loop:
	mov al, byte [rcx]	; salva byte str[rcx] em rax
	mov byte [r8], al	; copia byte da origem no buffer
	dec rcx			; byte anterior na string
	inc r8			; próximo byte no buffer
	cmp rcx, rsi		; rcx < início da string?
	jb .done		; se menor, termina
	jmp .write_loop
.done:
	mov byte [r8], 0	; garante terminador nulo
	mov rsi, rdi		; rsi => endereço do buffer
	ret
; ----------------------------------------------------------
str_len:
; ----------------------------------------------------------
; Descrição: obtém o tamanho da string em rsi.
; Entrada  : rsi -> char *str (endereço da string)
; Saída    : rax -> quantidade de caracteres excluindo '\0'
; Aletra   : rax (retorno), rcx
; ----------------------------------------------------------
	xor rax, rax		; zera rax para receber os bytes
	xor rcx, rcx		; contador = 0
.count_loop:
	mov al, byte [rsi+rcx]	; copia byte em rsi[rcx] para rax
	cmp al, 0		; o byte em rax é 0x00?
	je .done

	inc rcx			; contador += 1
	jmp .count_loop
.done:
	mov rax, rcx
	ret
; ----------------------------------------------------------
print_str:
; ----------------------------------------------------------
; Descrição: Imprime string em rsi.
; Entrada  : rsi -> char *src (endereço da string)
; Altera   : rax, rcx, rdx, rdi, r11	
; Depende de str_len!
; ----------------------------------------------------------
	call str_len		; retorna str_len em rax
	mov rdx, rax
	mov rax, SYS_WRITE
	mov rdi, STDOUT_FD
	syscall
	ret
; ----------------------------------------------------------
print_eol:
; ----------------------------------------------------------
; Descrição: Imprime uma quebra de linha.
; Entrada  : não tem entradas
; Altera   : rax, rcx, rdx, rdi, rsi, r11
; ----------------------------------------------------------
	push EOL_CHAR		; salva '\n' na pilha
	mov rax, SYS_WRITE
	mov rdi, STDOUT_FD
	mov rsi, rsp
	mov rdx, 1
	syscall
	add rsp, 8		; restaura o topo da pilha
	ret
; ----------------------------------------------------------
echo_str:
; ----------------------------------------------------------
; Descrição: Imprime string em rsi com uma quebra de linha.
; Entrada  : rsi -> char *src (endereço da string)
; Saída    : Nenhuma
; Altera   : rax, rcx, rdx, rdi, rsi, r11
; Depende de str_len, print_str e print_eol!
; ----------------------------------------------------------
	call print_str
	call print_eol
	ret
; ----------------------------------------------------------
i64_count_digits:
; ----------------------------------------------------------
; Descrição: Conta dígitos de uma constante inteira (int64).
; Entrada  : rdi -> Valor int64 (inteiro com ou sem sinal)
; Saída    : rax -> Quantidade de dígitos
; Altera   : rax (retorno), rcx, r8
; ----------------------------------------------------------
	mov r8, rdi		; salva rdi em r8
	test rdi, rdi		; verifica se inteiro é negativo
	jns .continue		; se não for, continua
	neg rdi			; rdi => valor positivo (absoluto)
.continue:
	cmp rdi, 0		; O número é 0?
	jne .count_start	; se não for, continua
	mov rax, 1		; 0 tem 1 dígito
	ret
.count_start:
	mov rax, 1		; contador de dígitos
	mov rcx, 10		; potência de 10 atual
.count_loop:
	cmp rdi, rcx		; num < 10^rax?
	jb .done
	inc rax			; incrementa o contador
	imul rcx, rcx, 10	; rcx = rcx * 10
	jmp .count_loop
.done:
	mov rdi, r8		; restaura rdi
	ret
; ----------------------------------------------------------
u64_to_str:
; ----------------------------------------------------------
; Descrição: Converte inteiro (uint64) para string.
; Entradas:
;   rdi -> valor uint64 (sem sinal)
;   rsi -> endereço do buffer de saída
; Saída:
;   rsi -> endereço do buffer
; Aletra: rax, rcx, rdx, r8
; Depende de i64_count_digits!	
; ----------------------------------------------------------
	call i64_count_digits	; retorna dígitos em rax
	mov rcx, rsi		; copia endereço inicial em rcx
	add rcx, rax		; rcx => fim da string + 1
	mov byte [rcx], 0	; terminador nulo
	dec rcx			; rcx => byte anterior no buffer
	
	mov rax, rdi		; copia valor para rax (dividendo)
	mov r8, 10		; r8 = 10 (divisor)
.convert_loop:
	xor rdx, rdx		; zera rdx para o resto (dígito)
	div r8			; rax = valor/10, rdx = valor%10
	add dl, 0x30		; converte resto para ASCII
	mov byte [rcx], dl	; salva caractere no buffer
	dec rcx			; endereço do byte anterior
	cmp rcx, rsi		; rsi < rcx?
	jb .done
	jmp .convert_loop
.done:
	ret
; ----------------------------------------------------------
	
%endif

Arquivo: `demo.asm` ```asm %include "pbn-utils.asm" %define BUF_SIZE 21 section .rodata txt: db "abcdefghij", 0 ; string com 10 caracteres + '\0' section .bss buf: resb BUF_SIZE ; espaço para 20 caracteres + '\0' section .text global _start _start: mov rdi, buf ; endereço do buffer mov rsi, txt ; endereço da string call write_buf ; copia string e retona buffer em rsi call echo_str ; imprime string no endereço em rsi _brev: mov rdi, buf ; endereço do buffer mov rsi, txt ; endereço da string call rev_buf ; inverte string e retorna buffer em rsi call echo_str ; imprime string no endereço em rsi _pu64: mov rdi, 123456 ; inteiro sem sinal 64 bits mov rsi, buf ; endereço do buffer call u64_to_str ; converte e retorna buffer em rsi call echo_str ; imprime string no endereço em rsi _exit: mov rax, SYS_EXIT mov rdi, EXIT_OK syscall ``` Arquivo: `pbn-utils.asm` ```asm %ifndef PBN_UTILS %define PBN_UTILS ; ---------------------------------------------------------- %define SYS_WRITE 1 %define SYS_EXIT 60 ; ---------------------------------------------------------- %define STDIN_FD 0 %define STDOUT_FD 1 %define STDERR_FD 2 ; ---------------------------------------------------------- %define EXIT_OK 0 %define EXIT_FAIL 1 ; ---------------------------------------------------------- %define EOL_CHAR 0x0a ; ---------------------------------------------------------- ; Sub-rotinas... ; ---------------------------------------------------------- ; - write_buf: copia string (rsi) para um buffer (rdi). ; - rev_buf : inverte e salva string (rsi) em um buffer (rdi). ; - str_len : obtém o tamanho de uma string (rsi). ; - print_str: imprime string (rsi) ; - print_eol: imprime quebra de linha. ; - echo_str : imprime string (rsi) com uma quebra de linha. ; - i64_count_digits: conta dígitos de um inteiro (base 10). ; - u64_to_str: converte inteiro sem sinal para string. ; ---------------------------------------------------------- write_buf: ; ---------------------------------------------------------- ; Descrição: Copia string em rsi no buffer em rdi. ; Entradas: ; rsi -> char *src (endereço da string) ; rdi -> char *buf (endereço do buffer) ; Saída: ; rsi -> char *buf (endereço do buffer) ; Aletra: rax, rcx, r8, rsi (retorno) ; ---------------------------------------------------------- mov rcx, rsi ; rcx => endereço da string mov r8, rdi ; r8 => endereço do buffer .write_loop: mov al, byte [rcx] ; copia byte em rsi para rax cmp al, 0 ; o byte em rax é 0x00? je .done mov [r8], al ; copia bite de 'txt' em 'buf' inc r8 ; próximo espaço em 'buf' inc rcx ; próximo byte da string jmp .write_loop .done: mov byte [r8], 0 ; garante terminador nulo mov rsi, rdi ; rsi => endereço do buffer ret ; ---------------------------------------------------------- rev_buf: ; ---------------------------------------------------------- ; Descrição: Inverte string em rsi e salva no buffer em rdi. ; Entradas: ; rdi -> char *buf (buffer para string invertida) ; rsi -> char *str (endereço da string) ; Saída: ; rsi -> char *buf (endereço do buffer) ; Aletra: rax, rcx, r8, rsi (retorno) ; Depende de str_len! ; ---------------------------------------------------------- call str_len ; retorna tamanho da string em rax mov r8, rdi ; r8 => endereço do buffer mov rcx, rsi ; rcx => endereço da string add rcx, rax ; rcx => terminador da string dec rcx ; rcx => último caractere .write_loop: mov al, byte [rcx] ; salva byte str[rcx] em rax mov byte [r8], al ; copia byte da origem no buffer dec rcx ; byte anterior na string inc r8 ; próximo byte no buffer cmp rcx, rsi ; rcx < início da string? jb .done ; se menor, termina jmp .write_loop .done: mov byte [r8], 0 ; garante terminador nulo mov rsi, rdi ; rsi => endereço do buffer ret ; ---------------------------------------------------------- str_len: ; ---------------------------------------------------------- ; Descrição: obtém o tamanho da string em rsi. ; Entrada : rsi -> char *str (endereço da string) ; Saída : rax -> quantidade de caracteres excluindo '\0' ; Aletra : rax (retorno), rcx ; ---------------------------------------------------------- xor rax, rax ; zera rax para receber os bytes xor rcx, rcx ; contador = 0 .count_loop: mov al, byte [rsi+rcx] ; copia byte em rsi[rcx] para rax cmp al, 0 ; o byte em rax é 0x00? je .done inc rcx ; contador += 1 jmp .count_loop .done: mov rax, rcx ret ; ---------------------------------------------------------- print_str: ; ---------------------------------------------------------- ; Descrição: Imprime string em rsi. ; Entrada : rsi -> char *src (endereço da string) ; Altera : rax, rcx, rdx, rdi, r11 ; Depende de str_len! ; ---------------------------------------------------------- call str_len ; retorna str_len em rax mov rdx, rax mov rax, SYS_WRITE mov rdi, STDOUT_FD syscall ret ; ---------------------------------------------------------- print_eol: ; ---------------------------------------------------------- ; Descrição: Imprime uma quebra de linha. ; Entrada : não tem entradas ; Altera : rax, rcx, rdx, rdi, rsi, r11 ; ---------------------------------------------------------- push EOL_CHAR ; salva '\n' na pilha mov rax, SYS_WRITE mov rdi, STDOUT_FD mov rsi, rsp mov rdx, 1 syscall add rsp, 8 ; restaura o topo da pilha ret ; ---------------------------------------------------------- echo_str: ; ---------------------------------------------------------- ; Descrição: Imprime string em rsi com uma quebra de linha. ; Entrada : rsi -> char *src (endereço da string) ; Saída : Nenhuma ; Altera : rax, rcx, rdx, rdi, rsi, r11 ; Depende de str_len, print_str e print_eol! ; ---------------------------------------------------------- call print_str call print_eol ret ; ---------------------------------------------------------- i64_count_digits: ; ---------------------------------------------------------- ; Descrição: Conta dígitos de uma constante inteira (int64). ; Entrada : rdi -> Valor int64 (inteiro com ou sem sinal) ; Saída : rax -> Quantidade de dígitos ; Altera : rax (retorno), rcx, r8 ; ---------------------------------------------------------- mov r8, rdi ; salva rdi em r8 test rdi, rdi ; verifica se inteiro é negativo jns .continue ; se não for, continua neg rdi ; rdi => valor positivo (absoluto) .continue: cmp rdi, 0 ; O número é 0? jne .count_start ; se não for, continua mov rax, 1 ; 0 tem 1 dígito ret .count_start: mov rax, 1 ; contador de dígitos mov rcx, 10 ; potência de 10 atual .count_loop: cmp rdi, rcx ; num < 10^rax? jb .done inc rax ; incrementa o contador imul rcx, rcx, 10 ; rcx = rcx * 10 jmp .count_loop .done: mov rdi, r8 ; restaura rdi ret ; ---------------------------------------------------------- u64_to_str: ; ---------------------------------------------------------- ; Descrição: Converte inteiro (uint64) para string. ; Entradas: ; rdi -> valor uint64 (sem sinal) ; rsi -> endereço do buffer de saída ; Saída: ; rsi -> endereço do buffer ; Aletra: rax, rcx, rdx, r8 ; Depende de i64_count_digits! ; ---------------------------------------------------------- call i64_count_digits ; retorna dígitos em rax mov rcx, rsi ; copia endereço inicial em rcx add rcx, rax ; rcx => fim da string + 1 mov byte [rcx], 0 ; terminador nulo dec rcx ; rcx => byte anterior no buffer mov rax, rdi ; copia valor para rax (dividendo) mov r8, 10 ; r8 = 10 (divisor) .convert_loop: xor rdx, rdx ; zera rdx para o resto (dígito) div r8 ; rax = valor/10, rdx = valor%10 add dl, 0x30 ; converte resto para ASCII mov byte [rcx], dl ; salva caractere no buffer dec rcx ; endereço do byte anterior cmp rcx, rsi ; rsi < rcx? jb .done jmp .convert_loop .done: ret ; ---------------------------------------------------------- %endif ```
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: blau_araujo/pbn#20
No description provided.