Soluções do desafio da aula 10 #18

Open
opened 2025-07-23 21:20:35 -03:00 by blau_araujo · 4 comments
Owner

Escreva nos comentários o código da sua implementação.

Escreva nos comentários o código da sua implementação.
section .text
global _start

_start:

    xor r8, r8
.args_loop:
    lea rdx, [rsp + 8 * r8 + 8]
    mov rsi, [rdx]
    test rsi, rsi
    jz _exit
    call echo_str
    inc r8
    jmp .args_loop

_exit:
    mov rax, 60
    xor rdi, rdi
    syscall

; ----------------------------------------------------------
echo_str:
; ----------------------------------------------------------
; Entradas:
;   rsi -> char *src (endereço da string)
;   rdx -> uint64 size (quantidade de bytes a imprimir)
; ----------------------------------------------------------
	call print_str
	call print_eol
	ret

; ----------------------------------------------------------
print_str:
; ----------------------------------------------------------
; Entradas:
;   rsi -> char *src (endereço da string)
;   rdx -> uint64 size (quantidade de bytes a imprimir)
; ----------------------------------------------------------
	push rsi
	call str_len	
	
	mov rdx, rax
	pop rsi

	mov rax, 1
	mov rdi, 1
	syscall
	ret

; ----------------------------------------------------------
str_len:
; ----------------------------------------------------------
; Entrada: rsi -> char *str (endereço da string)
; Saída  : rax -> quantidade de caracteres excluindo '\0'
; ----------------------------------------------------------
	xor rax, rax		; limpa rax para receber os bytes
	xor rcx, rcx		; contador = 0
.count_loop:
	mov al, byte [rsi]	; copia byte em rsi para rax
	cmp al, 0		; o byte em rax é 0x00?
	je .done
	
	inc rsi			; próximo byte
	inc rcx			; contador += 1
	jmp .count_loop
.done:
	mov rax, rcx
	ret

; ----------------------------------------------------------
print_eol:
; ----------------------------------------------------------
; Não tem entradas
; ----------------------------------------------------------
	push 0x0a		; salva '\n' na pilha
	mov rax, 1
	mov rdi, 1
	mov rsi, rsp
	mov rdx, 1
	syscall
	add rsp, 8		; restaura o topo da pilha
	ret

```asm section .text global _start _start: xor r8, r8 .args_loop: lea rdx, [rsp + 8 * r8 + 8] mov rsi, [rdx] test rsi, rsi jz _exit call echo_str inc r8 jmp .args_loop _exit: mov rax, 60 xor rdi, rdi syscall ; ---------------------------------------------------------- echo_str: ; ---------------------------------------------------------- ; Entradas: ; rsi -> char *src (endereço da string) ; rdx -> uint64 size (quantidade de bytes a imprimir) ; ---------------------------------------------------------- call print_str call print_eol ret ; ---------------------------------------------------------- print_str: ; ---------------------------------------------------------- ; Entradas: ; rsi -> char *src (endereço da string) ; rdx -> uint64 size (quantidade de bytes a imprimir) ; ---------------------------------------------------------- push rsi call str_len mov rdx, rax pop rsi mov rax, 1 mov rdi, 1 syscall ret ; ---------------------------------------------------------- str_len: ; ---------------------------------------------------------- ; Entrada: rsi -> char *str (endereço da string) ; Saída : rax -> quantidade de caracteres excluindo '\0' ; ---------------------------------------------------------- xor rax, rax ; limpa rax para receber os bytes xor rcx, rcx ; contador = 0 .count_loop: mov al, byte [rsi] ; copia byte em rsi para rax cmp al, 0 ; o byte em rax é 0x00? je .done inc rsi ; próximo byte inc rcx ; contador += 1 jmp .count_loop .done: mov rax, rcx ret ; ---------------------------------------------------------- print_eol: ; ---------------------------------------------------------- ; Não tem entradas ; ---------------------------------------------------------- push 0x0a ; salva '\n' na pilha mov rax, 1 mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall add rsp, 8 ; restaura o topo da pilha ret ```

Eu criei uma subrotina para fazer a impressão dos argumentos e usei echo_str nela.

Estou usando rcx como índice para iterar pelos argumentos, e como a syscall write manipula rcx no retorno da chamada, faço um push/pop de rcx antes e depois da impressão.

O deslocamento do lea é de 16, pq na chamada da subrotina rsp retrocede na pilha.

_start:
    call print_args
    call _exit

print_args:
    xor rcx, rcx
.loop:
    lea rdx, [rsp + 8 * rcx + 16]
    mov rsi, [rdx]

    test rsi, rsi
    jz .return

    push rcx
    call echo_str
    pop rcx

    inc rcx
    jmp .loop
.return:
    ret
Eu criei uma subrotina para fazer a impressão dos argumentos e usei echo_str nela. Estou usando rcx como índice para iterar pelos argumentos, e como a syscall write manipula rcx no retorno da chamada, faço um push/pop de rcx antes e depois da impressão. O deslocamento do lea é de 16, pq na chamada da subrotina rsp retrocede na pilha. ```asm _start: call print_args call _exit print_args: xor rcx, rcx .loop: lea rdx, [rsp + 8 * rcx + 16] mov rsi, [rdx] test rsi, rsi jz .return push rcx call echo_str pop rcx inc rcx jmp .loop .return: ret ```

Minha versão ficou bem parecida com os códigos disponibilizados, mas mudei alguns registradores no processo de reescrever do zero pra fixar o aprendizado.

Na _start usei o r10 como contador, pois o rcx era alterado em outras sub-rotinas. Criar o contador usando push ainda me dá nó na cabeça pelo fato que isso altera o rsp, então por enquanto ficou assim :)

section .text
global _start

; ----------------------------------------------------------

str_len:
    ; inputs:
    ; rsi -> const char*
    ; outputs:
    ; rax -> number of chars
    xor rcx, rcx
    xor rax, rax
.count_loop:
    mov al, byte [rsi]
    cmp al, 0
    je .done

    inc rcx
    inc rsi
    jmp .count_loop

.done:
    mov rax, rcx
    ret

; ----------------------------------------------------------

print_str:
    ; inputs:
    ; rsi -> const char*
    ; outputs:
    ; rax -> return value for syscall write
    push rsi
    call str_len
    mov rcx, rax
    pop rsi

    mov rax, 1
    mov rdi, 1
    mov rdx, rcx
    syscall
    ret

print_eol:
    push 0x0a   ; push '\0' onto the stack
    mov rax, 1
    mov rdi, 1
    mov rsi, rsp
    mov rdx, 1
    syscall
    add rsp, 8  ; pop 0x0a from the stack without saving its value
    ret

; ----------------------------------------------------------

_start:
    xor r10, r10                    ; set counter to zero
.argv_loop:
    mov rsi, [rsp + 8 + (8 * r10)]  ; rsi receives the address of argv[0]
    cmp rsi, 0
    je _exit_success

    call print_str
    call print_eol
    inc r10
    jmp .argv_loop

_exit_success:
    mov rax, 60
    xor rdi, rdi
    syscall

; ----------------------------------------------------------

Teste na linha de comando:

$ nasm -f elf64 -g print_args.asm
$ ld print_args.o
$ ./a.out salve simpatia aula 10 uhuuu
./a.out
salve
simpatia
aula
10
uhuuu

Minha versão ficou bem parecida com os códigos disponibilizados, mas mudei alguns registradores no processo de reescrever do zero pra fixar o aprendizado. Na `_start` usei o `r10` como contador, pois o `rcx` era alterado em outras sub-rotinas. Criar o contador usando `push` ainda me dá nó na cabeça pelo fato que isso altera o `rsp`, então por enquanto ficou assim :) ```asm section .text global _start ; ---------------------------------------------------------- str_len: ; inputs: ; rsi -> const char* ; outputs: ; rax -> number of chars xor rcx, rcx xor rax, rax .count_loop: mov al, byte [rsi] cmp al, 0 je .done inc rcx inc rsi jmp .count_loop .done: mov rax, rcx ret ; ---------------------------------------------------------- print_str: ; inputs: ; rsi -> const char* ; outputs: ; rax -> return value for syscall write push rsi call str_len mov rcx, rax pop rsi mov rax, 1 mov rdi, 1 mov rdx, rcx syscall ret print_eol: push 0x0a ; push '\0' onto the stack mov rax, 1 mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall add rsp, 8 ; pop 0x0a from the stack without saving its value ret ; ---------------------------------------------------------- _start: xor r10, r10 ; set counter to zero .argv_loop: mov rsi, [rsp + 8 + (8 * r10)] ; rsi receives the address of argv[0] cmp rsi, 0 je _exit_success call print_str call print_eol inc r10 jmp .argv_loop _exit_success: mov rax, 60 xor rdi, rdi syscall ; ---------------------------------------------------------- ``` Teste na linha de comando: ```bash $ nasm -f elf64 -g print_args.asm $ ld print_args.o $ ./a.out salve simpatia aula 10 uhuuu ./a.out salve simpatia aula 10 uhuuu ```
Author
Owner

@leandrossantos @morsoni @NRZCode, obrigado pelas suas soluções! Estudem suas abordagens, por favor, para ajudar a turma na aula.

@leandrossantos @morsoni @NRZCode, obrigado pelas suas soluções! Estudem suas abordagens, por favor, para ajudar a turma na aula.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
4 participants
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#18
No description provided.