started practicing with nasm this morning , so i graduated from helloworld to addition and subtraction and then area of a triangle
Now i want to get input (Like Prompts) from the user and then add or subtract or multiply
Following this code
how do i go about it
section .data
msg:
db 'Addition is = %d',10,0
section .text
extern _printf
global _main
_main:
push ebp
mov esp,epb
mov eax,5
add eax,2
push eax
push msg
call _printf
pop ebp
mov esp,ebp
ret
Related
This question already has answers here:
Linux write sys call using string on stack [duplicate]
(1 answer)
What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
(1 answer)
Closed 5 years ago.
I'm learning the NASM assembler and I have being stuck at the moment with handling the linefeed.
How do I print the linefeed? I'll show you. But, before I show it, it's important to tell you about my platform:
$ uname -a
Linux 4.4.0-97-generic #120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID : Ubuntu
Description : Ubuntu 16.04.3 LTS
Release : 16.04
Codename : xenial
My functions, which I have prepared for the learning:
sprint:
push rdx
push rbx
push rax
push rcx
mov rax, rcx
pop rcx
jmp next_char
ret
sprint_syscall:
mov rbx, 1
mov rax, 4
int 80h
pop rax
pop rbx
pop rdx
ret
sprint_linefeed:
call sprint
push rcx
mov rcx, 0Ah
push rcx
mov rcx, rsp
call sprint
pop rcx
pop rcx
ret
next_char:
cmp byte [rax], 0
jz count_length
inc rax
jmp next_char
count_length:
sub rax, rcx
mov rdx, rax
jmp sprint_syscall
quit:
push rbx
push rax
mov rbx, 0
mov rax, 1
int 80h
pop rax
pop rbx
ret
Main app, which may use one of the given functions:
%include 'functions.asm'
SECTION .data
msgFirst db "Hello World!", 0h
msgSecond db "Another string.", 0h
SECTION .text
global _start
_start:
mov rcx, msgFirst
call sprint_linefeed
mov rcx, msgSecond
call sprint_linefeed
call quit
All is compiling fine and works pretty too. If to compile/link with:
nasm -g -f elf64 -l main.lst main.asm -o main.o && ld main.o -o main
And then execute the compiled app, we're able to see:
Hello World!Another string
As you can see, there weren't any linefeed, despite on calling the sprint_linefeed function, which uses the next instructions for printing the linefeed:
sprint_linefeed:
call sprint
push rcx ; push rcx onto the stack to preserve it
mov rcx, 0Ah ; move 0Ah into rcx, 0Ah is the ASCII char for a linefeed
push rcx ; push the linefeed char onto the stack
mov rcx, rsp ; move the address of the pointer into rcx for the 'sys_write' syscall
call sprint
pop rcx ; remove the linefeed char from the stack
pop rcx ; restore the original value of rcx
ret
So, the explanation of my actions refers to sprint() call for the given string and then pushing the 0Ah char onto stack. Later, I'm getting the pointer from the RSP-register to call the sprint() function again.
It was done, because the SYS_WRITE syscall requires the pointer to print the give string (http://fresh.flatassembler.net/lscr/data/004.html).
If to add the OAh char to the string declaration:
SECTION .data
msgFirst db "Hello World!", 0Ah, 0h
Calling the same function, but with the different string value, gives us the awaited result, but it makes NO sense, because sprint_linefeed() was defined to pass the declaration of the redundant ASCII-char.
What should I fix in my source-code to make sprint_linefeed() work fine?
#Neverlands I made a minor change to your functions.asm by removing sprint_linefeed and put the following at the top of the file:
%define newline 0Ah
SECTION .data
lineEnding db newline, 0h
sprint_linefeed:
call sprint
mov rcx, lineEnding
call sprint
ret
It may not be exactly what you want but it does give:
Hello World!
Another string.
as output. Have fun!
my teacher is doing a crash course in assembly with us, and I have no experience in it whatsoever. I am supposed to write a simple function that takes four variables and calculates (x+y)-(z+a) and then prints out the answer. I know it's a simple problem, but after hours of research I am getting no where, any push in the right direction would be very helpful! I do need to use the stack, as I have more things to add to the program once I get past this point, and will have a lot of variables to store. I am compiling using nasm and gcc, in linux. (x86 64)
(side question, my '3' isn't showing up in register r10, but I am in linux so this should be the correct register... any ideas?)
Here is my code so far:
global main
extern printf
segment .data
mulsub_str db "(%ld * %ld) - (%ld * %ld) = %ld",10,0
data dq 1, 2, 3, 4
segment .text
main:
call multiplyandsubtract
pop r9
mov rdi, mulsub_str
mov rsi, [data]
mov rdx, [data+8]
mov r10, [data+16]
mov r8, [data+24]
mov rax, 0
call printf
ret
multiplyandsubtract:
;;multiplies first function
mov rax, [data]
mov rdi, [data+8]
mul rdi
mov rbx, rdi
push rbx
;;multiplies second function
mov rax, [data+16]
mov rsi, [data+24]
mul rsi
mov rbx, rsi
push rbx
;;subtracts function 2 from function 1
pop rsi
pop rdi
sub rdi, rsi
push rdi
ret
push in the right direction
Nice pun!
Your problem is that you apparently don't seem to know that ret is using the stack for the return address. As such push rdi; ret will just go to the address in rdi and not return to your caller. Since that is unlikely to be a valid code address, you get a nice segfault.
To return values from functions just leave the result in a register, standard calling conventions normally use rax. Here is a possible version:
global main
extern printf
segment .data
mulsub_str db "(%ld * %ld) - (%ld * %ld) = %ld",10,0
data dq 1, 2, 3, 4
segment .text
main:
sub rsp, 8
call multiplyandsubtract
mov r9, rax
mov rdi, mulsub_str
mov rsi, [data]
mov rdx, [data+8]
mov r10, [data+16]
mov r8, [data+24]
mov rax, 0
call printf
add rsp, 8
ret
multiplyandsubtract:
;;multiplies first function
mov rax, [data]
mov rdi, [data+8]
mul rdi
mov rbx, rdi
push rbx
;;multiplies second function
mov rax, [data+16]
mov rsi, [data+24]
mul rsi
mov rbx, rsi
push rbx
;;subtracts function 2 from function 1
pop rsi
pop rdi
sub rdi, rsi
mov rax, rdi
ret
PS: notice I have also fixed the stack alignment as per the ABI. printf is known to be picky about that too.
To return more than 64b from subroutine (rax is not enough), you can optionally drop the whole standard ABI convention (or actually follow it, there's surely a well defined way how to return more than 64b from subroutines), and use other registers until you ran out of them.
And once you ran out of spare return registers (or when you desperately want to use stack memory), you can follow the way C++ compilers do:
SUB rsp,<return_data_size + alignment>
CALL subroutine
...
MOV al,[rsp + <offset>] ; to access some value from returned data
; <offset> = 0 to return_data_size-1, as defined by you when defining
; the memory layout for returned data structure
...
ADD rsp,<return_data_size + alignment> ; restore stack pointer
subroutine:
MOV al,<result_value_1>
MOV [rsp + 8 + <offset>],al ; store it into allocated stack space
; the +8 is there to jump beyond return address, which was pushed
; at stack by "CALL" instruction. If you will push more registers/data
; at the stack inside the subroutine, you will have either to recalculate
; all offsets in following code, or use 32b C-like function prologue:
PUSH rbp
MOV rbp,rsp
MOV [rbp + 16 + <offset>],al ; now all offsets are constant relative to rbp
... other code ...
; epilogue code restoring stack
MOV rsp,rbp ; optional, when you did use RSP and didn't restore it yet
POP rbp
RET
So during executing the instructions of subroutine, the stack memory layout is like this:
rsp -> current_top_of_stack (some temporary push/pop as needed)
+x ...
rbp -> original rbp value (if prologue/epilogue code was used)
+8 return address to caller
+16 allocated space for returning values
+16+return_data_size
... padding to have rsp correctly aligned by ABI requirements ...
+16+return_data_size+alignment
... other caller stack data or it's own stack frame/return address ...
I'm not going to check how ABI defines it, because I'm too lazy, plus I hope this answer is understandable for you to explain the principle, so you will recognize which way the ABI works and adjust...
Then again, I would highly recommend to use rather many shorter simpler subroutines returning only single value (in rax/eax/ax/al), whenever possible, try to follow the SRP (Single Responsibility Principle). The above way will force you to define some return-data-structure, which may be too much hassle, if it's just some temporary thing and can be split into single-value subroutines instead (if performance is endangered, then probably inlining the whole subroutine will outperform even the logic of grouped returned values and single CALL).
section .data
msg db 'enter number ',10,0
output db '%hd',0
section .bss
val resw 1
section .text
global main
extern printf
extern scanf
main :
push msg
call printf
add esp,4
push val
push output
call scanf
add esp,8
;movzx eax,word[val]
;push eax
push word[val]
push output
call printf
add esp,8
ret
push word[val]
This only pushes a word and you need to have a dword on the stack.
You can do it like:
xor ax,ax
push ax ;Gives a high word of zero, much like your MOVZX did.
push word[val]
Your segmentation fault comes from the fact that you pushed a total of 6 bytes but removed a total of 8 bytes through add esp,8.
Me again, with the same kind of problems. So, this time I have created a small function that will display some text on the console. You push 2 arguments on the stack, call the function, see the text and return. This is the code:
start:
push dword MyText ; Pointer to the variable from the .data section
push dword 26 ; Number of characters to write
call ShowText
ret
ShowText:
push ebp
mov ebp, esp
push 0
push WrittenChars ; Pointer to the variable from the .bss section
push dword [ebp + 8] ; Number of characters to write
push dword [ebp + 12] ; MyText
push dword [StdHandle] ; Value of StdHandle, from the .bss section
call WriteConsoleA
pop ebp
ret
[section .data]
MyText db 'Abcdefghijklmnopqrstuvxzw', 0Ah
So, the correct values are pushed and retrieved by WriteConsoleA, the text is displayed correctly but I still get an Access Violation Error, so it looks like ESP is wrong after showing the message. I thought WriteConsoleA would clear the stack of its arguments, I don't know what happens.
ShowText has no pascal calling convetion, so in this case you must adjust the stack yourself.
call ShowText
add esp, 08
I have this linux nasm code here that doesn't crash. With the ret 80 instruction at the end of printString shouldn't this program crash?
bits 32
section .data
hello: db 'Hello Linux assembly!!!!!!!!!!!!!!!!!!!',10,0
helloLen: equ $-hello
anotherString db "hello im another string!!!!",10,0
anotherStringlen equ $-anotherString
section .text
global _start
_start:
push hello
push helloLen
call printString
;;;; should i pop the two paramters I pushed?
;;;; does the ret instruction do it for me?
push anotherString
push anotherStringlen
call printString
call exit
printString:
push ebp
mov ebp, esp
mov eax, 4
mov ebx, 1
mov ecx, [ebp+12]
mov edx, [ebp+8]
int 80h
pop ebp
ret 60 ;;;;; How does this not make printString crash?
exit:
mov eax,1
mov ebx,0
int 80h
Doing things incorrectly in assembly language by no means assures that you'll get a crash.
The ret 60 instruction pops the wrong number of values off the stack after returning. However, the next things you do don't assume that there are any values of use on the stack. For instance, the exit function won't care that the stack is trashed, and will still exit your process.