Declaring variables in Yasm - macos

Here's is a simple program:
%include 'utils/system.inc'
section .data
first: db 'First is bigger', 0xA,0
second: db 'Second is bigger', 0xA,0
a: db 18
b: db 20
section .text
global start
start:
mov rax, [a wrt rip]
mov rbx, [b wrt rip]
cmp rax, rbx
jle else
mov rsi, qword first
mov rdx, 0x10
jmp end
else:
mov rsi, qword second
mov rdx, 0x11
end:
xor rax, rax
xor rbx, rbx
mov rax, 0x2000004
mov rdi, stdout
syscall
xor rdi, rdi
mov rax, 0x2000001
syscall
The problem is that variable a contains a different value than 18.
Here's what lldb shows me:
(lldb) p a
(void *) $0 = 0x0000000000001412
(lldb) p b
(void *) $1 = 0x0000000000000014
(lldb) p --format decimal a
Any ideas what's going on? I know that if I declare a as dq, it will be alright, but I want to understand why it's happening.

Related

Reversing an array and printing it in x86-64

I am trying to print an array, reverse it, and then print it again. I manage to print it once. I can also make 2 consecutive calls to _printy and it works. But the code breaks with the _reverse function. It does not segfault, it exits with code 24 (I looked online but this seems to mean that the maximum number of file descriptors has been exceeded, and I cannot get what this means in this context). I stepped with a debugger and the loop logic seems to make sense.
I am not passing the array in RDI, because _printy restores the content of that register when it exits. I also tried to load it directly into RDI before calling _reverse but that does not solve the problem.
I cannot figure out what the problem is. Any idea?
BITS 64
DEFAULT REL
; -------------------------------------
; -------------------------------------
; PRINT LIST
; -------------------------------------
; -------------------------------------
%define SYS_WRITE 0x02000004
%define SYS_EXIT 0x02000001
%define SYS_OPEN 0x02000005
%define SYS_CLOSE 0x02000006
%define SYS_READ 0x02000003
%define EXIT_SUCCESS 0
%define STDOUT 1
%define LF 10
%define INT_OFFSET 48
section .text
extern _printf
extern _puts
extern _exit
global _main
_main:
push rbp
lea rdi, [rel array]
call _printy
call _reverse
call _printy
pop rbp
call _exit
_reverse:
push rbp
lea rsi, [rdi + 4 * (length - 1) ]
.LOOP2:
cmp rdi, rsi
jge .DONE2
mov r8, [rdi]
mov r9, [rsi]
mov [rdi], r9
mov [rsi], r8
add rdi,4
sub rsi,4
jmp .LOOP2
.DONE2:
xor rax, rax
lea rdi, [rel array]
pop rbp
ret
_printy:
push rbp
xor rcx, rcx
mov r8, rdi
.loop:
cmp rcx, length
jge .done
push rcx
push r8
lea rdi, [rel msg]
mov rsi, [r8 + rcx * 4]
xor rax, rax
call _printf
pop r8
pop rcx
add rcx, 1
jmp .loop
.done:
xor rax, rax
lea rdi, [rel array]
pop rbp
ret
section .data
array: dd 78, 2, 3, 4, 5, 6
length: equ ($ - array) / 4
msg: db "%d => ", 0
Edit with some info from the debugger
Stepping into the _printy function gives the following msg, once reaching the call to _printf.
* thread #1, queue = 'com.apple.main-thread', stop reason = step over failed (Could not create return address breakpoint.)
frame #0: 0x0000000100003f8e a.out`printf
a.out`printf:
-> 0x100003f8e <+0>: jmp qword ptr [rip + 0x4074] ; (void *)0x00007ff80258ef0b: printf
0x100003f94: lea r11, [rip + 0x4075] ; _dyld_private
0x100003f9b: push r11
0x100003f9d: jmp qword ptr [rip + 0x5d] ; (void *)0x00007ff843eeb520: dyld_stub_binder
I am not an expert, but a quick research online led to the following
During the 'thread step-out' command, check that the memory we are about to place a breakpoint in is executable. Previously, if the current function had a nonstandard stack layout/ABI, and had a valid data pointer in the location where the return address is usually located, data corruption would occur when the breakpoint was written. This could lead to an incorrectly reported crash or silent corruption of the program's state. Now, if the above check fails, the command safely aborts.
So after all this might not be a problem (I am also able to track the execution of the printf call). But this is really the only understandable piece of information I am able to extract from the debugger. Deep in some quite obscure (to me) function calls I reach this
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into
frame #0: 0x00007ff80256db7f libsystem_c.dylib`flockfile + 10
libsystem_c.dylib`flockfile:
-> 0x7ff80256db7f <+10>: call 0x7ff8025dd480 ; symbol stub for: __error
0x7ff80256db84 <+15>: mov r14d, dword ptr [rax]
0x7ff80256db87 <+18>: mov rdi, qword ptr [rbx + 0x68]
0x7ff80256db8b <+22>: add rdi, 0x8
Target 0: (a.out) stopped.
(lldb)
Process 61913 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into
frame #0: 0x00007ff8025dd480 libsystem_c.dylib`__error
This is one of the function calls happening in _printf.
Ask further questions if there is something more I can do.
Your array consists of int32 numbers aka dd in nasm terminology, but your swap operates on 64 bit numbers:
mov r8, [rdi]
mov r9, [rsi]
mov [rdi], r9
mov [rsi], r8
Assuming you were not after some crazy optimizations where you swap a pair of elements simultaneously you want this to remain in 32 bits:
mov r8d, [rdi]
mov r9d, [rsi]
mov [rdi], r9d
mov [rsi], r8d

Comparing input to character not working in x86_64 Mac assembly nasm

In nasm assembly on mac with the processor architecture x86_64, I am struggling to compare input to a string or character. When comparing input (stdin) to a character, it's not being true when it should be. I am new to assembly.
Here is my code.
global start
section .bss
input resb 10
section .text
start:
;getting the input
mov rax, 0x2000003 ;meaning read
mov rdi, 0
mov rsi, input
mov rdx, 10
syscall ;special
;here is where I do the comparing
mov rax, r
mov rbx, input
cmp rax, rbx
je right
;jumping to the return function
jmp ret
right:
mov rax, 0x2000004 ;meaning write
mov rdi, 1
mov rsi, right_way
mov rdx, right_len
syscall ;special
ret:
mov rax, 0x2000001 ;return 0
xor rdi, rdi ;which means to make rdi = 0 could be replaced with mov rdi, 0 but xor is faster
syscall
section .data
right_way: db "You are correct!", 10, 0
right_len: equ $-right_way
r: db "r", 10
At the "je right" line, it should jump to the right function but it does not. Do I need to convert the input to something else?
Help would be appreciated. Thanks!

How to break infinite loop assembly Windows x64

I'm trying to add arrA and arrB and store the values into arrC and print out.. once I run the code it takes me to infinite loop. How can I break the loop? Any suggestions greatly appreciated.
ExitProcess PROTO
WriteHex64 PROTO
.data
arrA BYTE 10h, 30h
arrB BYTE 0E0h, 40h
arrC BYTE 0, 0
string BYTE ", ", 00h
.code
main PROC
nop
mov rdi, OFFSET arrA
mov rsi, OFFSET arrB
mov rbx, OFFSET arrC
mov rdx, OFFSET string
mov rcx, LENGTHOF arrA
mov rax, 0
L1:
mov rax, [rdi]
mov rax, [rsi]
add rdi, TYPE arrA
add rsi, TYPE arrB
mov [rbx], rax
add rbx, TYPE arrC
call WriteHex64
call WriteString
loop L1
nop
mov ecx, 0
call ExitProcess
main ENDP
END

How to sort signed numbers using assembly language?

I have this homework wherein I need to make a program that asks three SIGNED numbers from the user and my program should be able to sort these numbers in ascending order. I can do it in C++ but I am not that familiar with NASM/Assembly Language.
Here's my code so far:
%include "asm_io.inc"
segment .data
;
; Output strings
;
prompta db "Enter the 1st number: ", 0
promptb db "Enter the 2nd number: ", 0
promptc db "Enter the 3rd number: ", 0
promptd db "The sorted list is: ", 0
segment .bss
input resd 1
segment .text
global _asm_main
_asm_main:
enter 0,0 ; setup routine
pusha
mov eax, prompta
call print_string
call read_int
push eax
mov eax, promptb
call print_string
call read_int
push eax
mov eax, promptc
call print_string
call read_int
push eax
call add_stack
mov ebx, eax
mov eax, promptd
call print_string
mov eax, ebx
call print_int
call print_nl
sub esp, 16
popa
mov eax, 0 ; return back to C
leave
ret
segment .data
; no need for .data
segment .bss
; no need for variables
segment .text
add_stack:
enter 0,0
mov ecx, [ebp+8]
mov ebx, [ebp+12]
mov eax, [ebp+16]
cmp eax, ebx
jg A
cmp ebx, ecx
jg B
cmp ecx, eax
jg C
A:
push eax
B:
push ebx
C:
push ecx
popa
leave
ret
In C++ you cannot change the arguments inside of a function and use it later by the caller, but in assembly you can do everything. You pushed the input onto the stack for later using as arguments for the function add_stack. What about to sort these values and store them back to the original place on the stack:
%include "asm_io.inc"
segment .data
;
; Output strings
;
prompta db "Enter the 1st number: ", 0
promptb db "Enter the 2nd number: ", 0
promptc db "Enter the 3rd number: ", 0
promptd db "The sorted list is: ", 0
segment .text
global _asm_main
_asm_main:
enter 0,0 ; setup routine
pusha
mov eax, prompta
call print_string
call read_int
push eax
mov eax, promptb
call print_string
call read_int
push eax
mov eax, promptc
call print_string
call read_int
push eax
call sort_stack ; Three arguments pushed before
mov eax, promptd
call print_string
mov ecx, 3 ; Pop and write the arguments for `sort_stack`
.print_list:
pop eax
call print_int
mov al, 32
call print_char
loop .print_list
call print_nl
popa
mov eax, 0 ; return back to C
leave
ret
sort_stack:
enter 0,0
mov ecx, [ebp+8]
mov ebx, [ebp+12]
mov eax, [ebp+16]
cmp eax, ebx
jg .1
xchg eax, ebx
.1:
cmp ebx, ecx
jg .2
xchg ebx, ecx
.2:
cmp eax, ebx
jg .3
xchg eax, ebx
.3: ; Write back the registers
mov [ebp+8], ecx
mov [ebp+12], ebx
mov [ebp+16], eax
leave
ret
I'm not sure, if your teacher will like this "trick".

Loading "/bin/sh" into a register

I'm trying to write ASM code to spawn a shell.
I've figured out that the syscall number for __execve is 0x3b or 59.
I need to send "/bin/sh" as the first parameter, a pointer to {"/bin/sh", NULL} as the second parameter and NULL as the third parameter.
By the convetions of x86_64 ASM on the Intel architecture - the first parameter is written into the RDI register, the second parameter is written into the RSI register and the final parameter is written into the RDX register.
This is my code:
global _start
section .text
_start:
jmp message
mystart:
xor rax, rax
push rax
push rax
pop rdx ; third parameter - NULL
pop rdi ; first parameter - "/bin/sh"
mov rax, rdi
push rax
push rsp
pop rsi ; second parameter - pointer to {"/bin/sh", NULL}
xor rax, rax
mov al, 0x3b
syscall
xor rax, rax
mov al, 0x3c
xor rdi, rdi
mov dil, 0x0a
syscall
message:
call mystart
db "/bin/sh"
section .data
I use the following instructions to compile and link the code.
yasm -f elf64 shell.asm -o shell.o
ld -o shell.out shell.o
The GDB dump of the _start function is as follows:
Dump of assembler code for function _start:
0x0000000000400080 <+0>: jmp 0x4000a3 <_start+35>
0x0000000000400082 <+2>: xor rax,rax
0x0000000000400085 <+5>: push rax
0x0000000000400086 <+6>: push rax
0x0000000000400087 <+7>: pop rdx
0x0000000000400088 <+8>: pop rdi
0x0000000000400089 <+9>: mov rax,rdi
0x000000000040008c <+12>: push rax
0x000000000040008d <+13>: push rsp
0x000000000040008e <+14>: pop rsi
0x000000000040008f <+15>: xor rax,rax
0x0000000000400092 <+18>: mov al,0x3b
0x0000000000400094 <+20>: syscall
0x0000000000400096 <+22>: xor rax,rax
0x0000000000400099 <+25>: mov al,0x3c
0x000000000040009b <+27>: xor rdi,rdi
0x000000000040009e <+30>: mov dil,0xa
---Type <return> to continue, or q <return> to quit---
0x00000000004000a1 <+33>: syscall
0x00000000004000a3 <+35>: call 0x400082 <_start+2>
0x00000000004000a8 <+40>: pop rsp
0x00000000004000a9 <+41>: (bad)
0x00000000004000aa <+42>: (bad)
0x00000000004000ab <+43>: .byte 0x69
0x00000000004000ac <+44>: outs dx,BYTE PTR ds:[rsi]
0x00000000004000ad <+45>: pop rsp
0x00000000004000ae <+46>: (bad)
0x00000000004000af <+47>: jae 0x400119
As you can see the (bad) instructions are caused by db "/bin/sh", what is wrong with this string? What is a (bad) instruction? How do I debug such problems in the future?
① You cannot load a string into a register, only a pointer to a string.
② Your stack magic is merely wrong. Move one of the doubled push rax to just below pop rdi, and the program works for me.

Resources