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.
Related
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
I'm new to assembly. I'm having different output for following simple code from what I expected. each time before printf is called, content of eax is shifted to the right by some number. What am I doing wrong? Thanks.
Code:
;file name : testing.asm
;assemble and link with:
;nasm -f elf testing.asm && gcc -m32 -o testing testing.o
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 15 ; int a=15
str: db "content in eax=%d", 10, 0
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
mov ebp, esp
mov eax, [a] ; put a from store into register
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
shr eax, 1
push eax ; eax content should be 1>>1 = 0
push dword str
call printf ; printf(str,content_of_eax)
mov esp, ebp ; takedown stack frame
mov eax, 0 ; normal, no error, return value
ret ; return
Output:
content in eax=7
content in eax=4
content in eax=8
Expected Output:
content in eax=7
content in eax=1
content in eax=0
printf returns its result in eax, the original value is lost.
You should reload it from [a] or use a register that is saved across function calls such as esi, but you should save it as well and restore it before returning to the caller. You should pop the arguments passed to printf with a add esp,8 after each call to keep your stack frame consistent.
In your data section you could just use an equate for a since you only use that variable once and do not change it (i'll call it value).
fmt db "content in eax=%d",0xa,0
value equ 15
In the main function i'm pretty sure (correct me if i'm wrong) that you're supposed to save the base pointer before you update it with the stack pointer.
main:
push ebp
mov ebp, esp
Now you could create a local variable to store the current value you are working on.
sub esp, 4
From there you would just keep fetching, shifting and storing the value on the stack before each call to printf.
mov eax, value ; move 15 into eax
shr eax, 1 ; make first shift
mov dword[ebp-4], eax ; store result in local variable
push eax ; eax = 7
push fmt
call printf
add esp, 8 ; clean eax & fmt off the stack
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 2 ; make second shift
mov dword[ebp-4], eax ; store result back in variable
push eax ; eax = 1
push fmt
call printf
add esp, 8
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 1 ; make last shift
push eax ; eax = 0
push fmt
call printf
add esp, 8
add esp, 4 ; clean local variable
And then remember, before you return, when you release the stack frame that you also restore (pop) the base pointer.
mov esp, ebp
pop ebp
This should output:
content in eax=7
content in eax=1
content in eax=0
Remember that printf will return the number of characters transmitted to the output. So when you do this:
call printf ; printf(str,content_of_eax)
shr eax, 2
You are actually shifting the result from printf:
"content in eax=7\n" is 17 characters, so shitfting by 2 gives: 17 / 4 = 4
You need to save the value (either in a preserved register, on the stack or in memory) before shifting.
This answer seems not to be a good solution, I'm currently keeping it because of the discussion below
Like others said, printf will return it's result to eax. The result of printf is the number of bytes written.
Since you pushed the result of the shr operation to the stack, you can retrieve them again using pop, like this:
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
pop eax
pop eax
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
# and so on ...
Having trouble using a string array and getting each character from it and adding a 1 to a frequency table of the corresponding ascii index (frequency table is indexed by ascii value): Example, get character 'a' then add 1 to the frequency table of index of the array ['a']. I was getting segmentation errors and now getting error: invalid combination of opcode and operands, talking about mov ax, al
Any questions about the parameters of the problem please ask. I have working on this for hours and could really use another pair of eyes to check what I am doing wrong (syntax/concept if you see one) Please help.
Update: I have got it print stuff out, so I think it is "working"; however I am now trying to print the characters that each array index corresponds. It won't print the character of the array that I am pointing to (it prints literally nothing for the character).
Latest update: I got it to work. changed some of the code under the label .loopa and now it works fine! :)
Code below:
SECTION .data ; Data section, initialized variables
array5: db "Hello, world...", 0
array5Len: equ $-array5-1
asoutput: db "%s", 0 ; string output
newline: db "", 10, 0 ; format for a new line
acoutput: db "%c: ", 0 ; output format for character output
SECTION .bss ; BSS, uninitialized variables
arrayq: resd 128 ; frequency array of the first 127 ascii values initialized to 0 (none have been counted yet)
SECTION .text
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; set up stack frame
mov ebp,esp
mov esi, array5
mov edi, 0
mov ebx, arrayq
mov ecx, array5Len
; get each character of array5 and add 1 to the frequency table of the corresponding ascii value (which the arrayq is indexed by ascii value).
.loopf:
xor eax, eax
mov al, [esi]
;mov ax, [esi]
;mov ax, al
;mov cx, ax
add edi, eax
mov ebx, 1
add [arrayq+4*edi], ebx
mov edi, 0
add esi, 1
loop .loopf
push dword array2
push dword asoutput
call printf
add esp, 8
push dword newline
call printf
add esp, 4
;pop ebx
mov ebx, arrayq
mov ecx, 128 ; size of arrayq
mov esi, 0 ;start at beginning
.loopa:
mov eax, 0
cmp [ebx+esi], eax
je .skip
mov eax, esi
push ebx
push ecx
mov ebx, 4
cdq
div ebx
push eax
push dword acoutput
call printf
add esp, 8
pop ecx
pop ebx
push ebx
push ecx ; make sure to put ecx (counter) on stack so we don't lose it when calling printf)
push dword [ebx + esi] ; put the value of the array at this (esi) index on the stack to be used by printf
push dword aoutput ; put the array output format on the stack for printf to use
call printf ; call the printf command
add esp, 8 ; add 4 bytes * 2
pop ecx ; get ecx back
pop ebx
push ebx
push ecx
push dword newline
call printf
add esp, 4
pop ecx
pop ebx
.skip:
add esi, 4
loop .loopa
.end:
mov esp, ebp ; takedown stack frame
pop ebp ; same as "leave" op
Changed code under .loopa label to make it print the character the index is corresponding to:
.loopa:
mov eax, 0
cmp [ebx+esi], eax
je .skip
mov eax, esi
push ebx
push ecx
mov ebx, 4
cdq
div ebx
push eax
push dword acoutput
call printf
add esp, 8
pop ecx
pop ebx
I'm learning NASM at the moment and am making a simple program that does multiplication of any user-input variables through shifting and addition.
I've been running into a series of issues: My multiplicand is, for some reason, being given at the maximum data value a word can hold. Furthermore, my answer, if the program should get that far, is almost always wrong (even though I believe my algorithm is correct!).
extern printf
extern scanf
section .data
message: db "Enter your multiplicand: "
message_L: equ $-message
message2: db "The number you entered is: %d ", 10, 0
message2_L: equ $-message2
message3: db "Enter your multiplier: "
message3_L: equ $-message3
message4: db "Your multiplier is: %d ", 10, 0
message4_L: equ $-message4
message5: db "The product of this multiplication is: %d ", 10, 0
mesasge5_L: equ $-message5
fmt1: db "%d", 0
section .bss
multiplicand: resw 1
multiplier: resw 1
product: resw 1
section .text
global main
scanInt:
push ebp
mov ebp, esp
sub esp, 2
lea eax, [ebp-2]
push eax
push dword fmt1
call scanf
mov ax, word[ebp-2]
mov esp, ebp
pop ebp
ret
main:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, message_L
int 80h
call scanInt
mov word[multiplicand], ax
mov word[product], ax
jmp print1
main2:
mov eax, 4
mov ebx, 1
mov ecx, message3
mov edx, message3_L
int 80h
call scanInt
mov word[multiplier], ax
jmp print2
main3:
mov ax, word[multiplicand]
jmp check
check:
cmp word[multiplier], 2
jz printAnswer
ror [multiplier], 1
shl word[multiplier], 1
jc carry
shr word[multiplier], 1
shr word[multiplier], 1
shl word[product], 1
jmp check
carry:
add word[product], ax
shr word[multiplier], 1
clc
jmp check
endLoop:
mov eax, 1
mov ebx, 0
int 80h
printAnswer:
push ebp
mov ebp, esp
push word[product]
push dword message5
call printf
add esp, 12
mov esp, ebp
pop ebp
jmp endLoop
print1:
push ebp
mov ebp, esp
push dword[multiplicand]
push dword message2
call printf
add esp, 12
mov esp, ebp
pop ebp
jmp main2
print2:
push ebp
mov ebp, esp
push dword[multiplier]
push dword message4
call printf
add esp, 12
mov esp, ebp
pop ebp
jmp main3
I think your main problem comes from using word variables. Making a two-byte buffer on the stack, and calling scanf to read into it is almost certainly a problem. Pushing a word in 32-bit code is "legal", but likely to cause problems. In one instance, you call printf with two variables, and add esp, 12 afterwards. Make 'em all dwords and keep your stack manipulation in four-byte chunks. I think that'll cure most of your problems.
The man pages explicitly suggest not mixing high-level, buffered I/O, functions with low level functions (printf, scanf, fopen(), fread(), fwrite(), etc. are high level functions, open(), read(), write()... and system calls are low level functions). I don't think that this is causing any of your problems, but it can cause weird results. For example, printf doesn't print anything until the buffer is flushed. Ending with a linefeed, or using another high level I/O function will flush the buffer. sys_read, for example, does not. I'd stick to one or the other.
Good luck!
I have written a program in NASM in Ubuntu11.04 which will take 2 input numbers and produce a sum. The program is the following:
section .data
msg1: db "the numbers are:%d%d",0
msg3: db "REsult= %d",10,0
section .bss
a resd 1
b resd 1
sum resd 1
section .text
global main
extern printf,scanf
main:
;; push ebp
;; mov ebp,esp
;; sub esp,10
push a
push b
push msg1
call scanf
add esp,12
mov eax,DWORD[a]
add eax,DWORD[b]
mov DWORD[sum],eax
push DWORD[sum]
push msg3
call printf
add esp,8
;; mov esp,ebp
;; pop ebp
ret
Will you pls help me to find out the mistake I have done here? I will also appreciate if you advice me any tutorial in NASM whether it is Vedio or text. I have gotten Art of Assembly Language or NASM Manual. But frst one is not based on NASM and 2nd one is difficult to get for a beginner like me.
Thanx
This should get you going:
global main
extern printf, scanf, exit
section .data
scanf_fmt db "%d %d", 0
printf1_fmt db "The numbers entered are: %d and %d,", " The result = %d", 10, 0
main:
push ebp
mov ebp, esp
sub esp, 8 ; make room for 2 dwords
lea eax, [ebp - 4] ; get pointers to our locals
lea ecx, [ebp - 8] ;
push eax ; give pointers to scanf
push ecx ;
push scanf_fmt ;
call scanf ; read in 2 dwords
add esp, 12
mov eax, dword [ebp - 4] ; add em together
add eax, dword [ebp - 8] ;
push eax ; total
push dword [ebp - 4] ; second num
push dword [ebp - 8] ; first num
push printf1_fmt ; format string
call printf ; show it
add esp, 16
add esp, 8 ; restore stack pointers
mov esp, ebp
pop ebp
call exit ; linking agaist the c libs, must use exit.
output: