section .data
text db 'Put a number',10,0
scanform db '%d'
number dw 0
section .text
extern printf,scanf
global main
main:
push rbp
mov rbp,rsp
push rdi
push rsi
push rbx
mov rdi,text
mov rax,0
call printf
mov rsi,number
mov rdi,scanform
mov rax,0
call scanf
pop rbx
pop rsi
pop rdi
ret
This is my code I write a other codes all day and I do not have problem with these but now when I call scanf, write program received signal SIGSEV, segfault... Specified first and last line in different files. I do not understand this message can someone help me?
You have the following issues:
You forgot to pop rbp.
You misalign the stack which needs to be 16 byte aligned.
You do not zero terminate your format string (thanks to Paul for pointing this out).
You use %d which writes a 4 byte integer but you only allocated 2 bytes with dw.
It is recommended to align integers to 4 bytes.
A possible fixed version:
section .data
number dd 0
text db 'Put a number',10,0
scanform db '%d', 0
section .text
extern printf,scanf
global main
main:
push rbp
mov rbp,rsp
push rdi
push rsi
push rbx
push rbx ; for alignment
mov rdi,text
mov rax,0
call printf
mov rsi,number
mov rdi,scanform
mov rax,0
call scanf
pop rbx
pop rbx
pop rsi
pop rdi
pop rbp
ret
Since rsi and rdi are caller-saved registers and rbx is not touched, you can simplify the code. I also changed to xor zeroing and rip-relative addressing as follows:
section .data
number dd 0
text db 'Put a number',10,0
scanform db '%d', 0
section .text
extern printf,scanf
global main
main:
push rbp
lea rdi, [rel text]
xor eax, eax
call printf
lea rsi, [rel number]
lea rdi, [rel scanform]
xor eax, eax
call scanf
pop rbp
ret
Related
I know the x64 calling convention, first four arguments are in rcx, rdx, r8, r9, rest are on the stack. But my question is how push these arguments?
call_func PROC
push rbp
mov rbp, rsp
mov rbx, rcx ; move C function address to rbx
mov rcx, 1 ; some dummy value
mov rdx, 2 ; some dummy value
mov r8, 3 ; some dummy value
mov r9, 4 ; some dummy value
; and now I want to push fifth argument, but how?
call rbx ; call the function
mov rsp, rbp
pop rbp
ret
call_func ENDP
I have tried mov QWORD PTR [rsp + 20h], 1 but when returning form this asm function the RIP register is set to weird value, like 0x0000000000000001. I know that the RIP register is instruction pointer, but why it is modifying it?
I have tried one more thing, let the function take 6 arguments and when I pass sixth argument like mov QWORD PTR [rsp + 28h], 1 the app is fine, sixth argument is passed, fifth has weird value.
As Jester said, before pushing arguments I need to allocate space for these arguments including shadow space.
Final working code:
call_func PROC
push rbp
mov rbp, rsp
sub rsp, 32 ; allocate shadow space 'padding'
sub rsp, 16 ; allocate space for fifth and sixth argument
mov r11, rcx ; move C function address to r11
mov rcx, 1 ; some dummy value
mov rdx, 2 ; some dummy value
mov r8, 3 ; some dummy value
mov r9, 4 ; some dummy value
mov QWORD PTR [rsp + 20h], 5 ; push fifth argument
mov QWORD PTR [rsp + 28h], 6 ; push sixth argument
call r11 ; call the function
mov rsp, rbp
pop rbp
ret
call_func ENDP
the following code tries to read the command line arguments and then scans them with sscanf() and use the result to emit utf8 text.
I'm failing to call sscanf() and getting segfault error at the line where I call this function
I have already debugged this and I know where is the problem but not how to solve it.
global main
extern puts
extern sscanf
extern printf
extern emit_utf_8
section .text
main:
cmp rdi, 2
jl argumentsError
add rsi, 8 ; skip the name of the program
forloop:
mov r12, rsi
push rdi
push rsi
push r12
sub rsp, 8 ; must align stack before call
; start of for bloc
xor rax, rax
mov rdi, qword [r12]
mov rsi, codePointFormat
mov rdx, qword [codePoint]
call sscanf
cmp rax, 1
je ifthen
jmp else
ifthen:
mov rdi, codePoint
call emit_utf_8
jmp endif
else:
mov rdi, incorrectFormat
mov rsi, r12
call printf
endif:
; end of for bloc
add rsp, 8 ; restore %rsp to pre-aligned value
pop r12
pop rsi
pop rdi
add rsi, 8 ; point to next argument
dec rdi ; count down
jnz forloop ; if not done counting keep going
ret
argumentsError: mov rdi, argumentsRequiredMessage
call puts
mov rdi, argumentDescription
call puts
xor rax, rax
inc rax
ret
section .data
argumentsRequiredMessage:
db "This program requires one or more command line arguments,", 0
argumentDescription: db "one for each code point to encode as UTF-8.", 0
incorrectFormat: db "(%s incorrect format)", 0
codePointFormat: db "U+%6X", 0
section .bss
codePoint: resb 8 ; The code point from sscanf should go here.
Is there a way to pass that third argument?
sscanf() signature.
in __cdecl sscanf(const char *const _buffer, const char *const _Format, ...)
I'm using ubuntu 19.04 64 bit
I try to print an integer using printf in x86 assembly. For the format string printf(fmtstring, vals) i have stored the %d as fmtd. Then i put 1 into ax, 2 into bx, add them and want to print the result using call printf. Here is the code.
global _main
extern _printf
section .data
fmtd db "%d"
section .text
_main:
push ebp
mov ebp, esp
_begin:
mov ax, 1
mov bx, 2
add ax, bx
push ax
push fmtd
call _printf
add esp, 8
_end:
mov esp, ebp
pop ebp
ret
but i get
-10485757
instead of expected
3
can you help me whats wrong with it?
When i just write
push 3
push fmtd
call _printf
it works as usual and prints 3.
Thank you
You need to use the full 32 bit registers:
You want this:
mov eax, 1
mov ebx, 2
add eax, ebx
push eax
push fmtd
call _printf
Explanation of output -10485757 you get:
-10485757 in hexadecimal is FF600003. The 0003 comes from the push ax which pushes the 16 low bits of eax. The FF60 is whatever leftover was on the stack.
Reads this SO article for detailed explanation about the relationship between ax and eax.
I am trying to write a nasm program that can move and print dynamic arrays using malloc and printf. The program sometimes crashes and sometimes works when it tries to print an array. When I edit the code so that it doesn't print anything, the program always works. The method "movad" sets a dynamic array equal to another array and "setad" sets an array to a static array that was declared at the beginning of the program. The array variable stores a pointer to a malloced piece of memory that stores the array. The first dword of the array is the length and the rest is the contents.
Here is the code:
%include "io.inc"
CEXTERN malloc
section .data
fmt: db "%c%c %c%c",0
start: dd 2
dd 'a'
dd 'b'
section .bss
array1: resd 1
array2: resd 1
a: resd 1
section .text
global _main
_main:
push ebp
mov ebp,esp
push dword start
push dword array1
call setad
add esp,8
push dword array1
push dword array2
call movad
add esp,8
mov ebx,[array2]
push dword [ebx+8]
push dword [ebx+4]
mov ebx,[array1]
push dword [ebx+8]
push dword [ebx+4]
push dword fmt
call printf
add esp,20
mov esp,ebp
pop ebp
ret
movad:
push ebp
mov ebp,esp
push ebx
push ecx
push edi
push esi
mov edi,[ebp+8]
mov esi,[ebp+12]
mov ebx,[esi]
push dword [ebx]
add dword [esp],4
call malloc
add esp,4
mov [edi],eax
mov ecx,[esi]
mov ecx,[ecx]
add ecx,1
mov edi,[edi]
mov esi,[esi]
cld
rep movsd
pop esi
pop edi
pop ecx
pop ebx
mov esp,ebp
pop ebp
ret
setad:
push ebp
mov ebp,esp
push eax
lea eax,[ebp+12]
push eax
push dword [ebp+8]
call movad
add esp,8
pop eax
mov esp,ebp
pop ebp
ret
How can I make it so that it never crashes when it prints something
I'm stuck at figuring out to copy the string source to target, which should be initialized to all zeroes. It appears as though I need to find the size of the string, start a counter register, and push stringitem[counter] to the stack, increment counter register. I can't figure out how to even get started, let alone search for a word in the string.
Thanks!
bits 64
global main
extern printf
section .text
main:
; function setup
push rbp
mov rbp, rsp
sub rsp, 32
;
lea rdi, [rel message]
mov al, 0
call printf
;
lea rdi, [rel source]
mov al, 0
call printf
;
;mov edi, source
;mov esi, target
;lea rdi, [esi]
;mov al, 0
;call printf
;mov ecx,sizeof source -1
; mov esi,0
;L1:
; mov eax,source[esi];
; push eax
; inc esi
; loop L1
; function return
mov eax, 0
add rsp, 32
pop rbp
ret
section .data
message: db 'Project',0x0D,0x0a,'Author',0x0D,0x0a,0
source: db 0x0D,0x0a,"I can't figure out how to copy this text to target.",0x0D,0x0a,0
target: db '0000000000000000000000000000000000000000000',0x0D,0x0a,0
For your data memory layout this will do
lea rdi, [rel target]
lea rsi, [rel source]
mov rcx, target-source
cld
rep movsb
Otherwise as Jester said, a simple byte-to-byte copy will also do
lea rdi, [rel target]
lea rsi, [rel source]
cld
.copy:
lodsb
stosb
test al, al
jnz .copy