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.
Related
section .data:
msg1: db "Hello 10 times!"
msglen1: equ $-msg1
section .text:
global _initial:
global _start:
global _end:
_initial:
mov cx,10
_start:
dec cx
mov ecx,msg1
mov edx,msglen1
mov eax,4
int 80h
cmp cx,0
jz _end
jmp _start
_end
mov eax,1
int 80h
Above code had to be produce "Hello 10 times" 10 times.But it getting go into infinite loop,and i couldn't understand why ?
i think cx register doesn't decrease or whatever else ?
You have a number of problems.
The default entry point for a Linux program is _start. Your program starts by executing at label _start not at initial so your loop counter isn't being initialized.
Section names do not have a : on the name, and neither do labels for the global1
You are missing a parameter for the SYS_Write system call. The 32-bit system calls are documented in a table:
You need to set EBX to a file descriptor. STDIN=0, STDOUT = 1, STDERR=2. You want to write to the console so you need to set EBX to 1 before calling Int 80h
You are clobbering one of the parameters (ECX) to the SYS_Write system call. CX and ECX are part of the same register. CX is the lower 16-bits of ECX. Changing CX changes ECX. You need to use some other register for the loop counter. ESI, EDI, and EBP are currently unused in your code. Change all occurrences of CX to the 32-bit register ESI.
Your code could look like:
section .data
msg1: db "Hello 10 times!", 10
; Add 10 on the end of the string for Line Feed
; so each message prints on separate line
msglen1 equ $-msg1
section .text
global _initial
global _start
global _end
_start:
mov esi, 10 ; Initialize loop counter
_msgloop:
dec esi ; Decrement loop counter
mov ebx, 1 ; File Descriptor 1 = Write to Standard Output (STDOUT)
mov ecx, msg1 ; Address of message to print
mov edx, msglen1 ; Length of message to print
mov eax, 4 ; SYS_Write system call = 4
int 80h
cmp esi, 0 ; Has the loop counter reached 0?
jz _end ; If it has then we are done
jmp _msgloop ; otherwise go back and print message again
_end:
mov eax,1 ; SYS_Exit system call
int 80h
You could have rewritten your loop this way:
section .data
msg1: db "Hello 10 times!", 10
; Add 10 on the end of the string for Line Feed
; so each message prints on separate line
msglen1 equ $-msg1
section .text
global _start
_start:
mov esi, 10 ; Initialize loop counter
.msgloop:
mov ebx, 1 ; File Descriptor 1 = Write to Standard Output (STDOUT)
mov ecx, msg1 ; Address of message to print
mov edx, msglen1 ; Length of message to print
mov eax, 4 ; SYS_Write system call = 4
int 80h
dec esi ; Decrement loop counter
jnz .msgloop ; If loop counter hasn't reached zero then print again
mov eax,1 ; SYS_Exit system call
int 80h
Footnotes:
1You don't need to make initial and end global since you aren't linking to any other object files. Those global lines can be removed.
You're trying to use the cx register for your loop count, while needing to use ecx as a parameter for your output. Since cx is the lower 16 bits of ecx, you clobber your loop count.
You need to either use some other register (that is not used during the system call) for you loop count, or store the count in a local variable on the stack.
I'm writing an assembly program that would print even numbers between 0-9 using a loop. I encountered this problem, segmentation fault while running the code. I check other answers on the site but couldn't find an answer that satisfies my issue.
I suspect that the function nwLine might be the source of the problem.
;;this program prints even numbers from 0-8 using loop function
section .text
global _start
cr db 10
_start: ;tell linker entry point
mov ecx, 5
mov eax, '0'
evenLoop:
mov [evnum], eax ;add eax to evnum
mov eax, 4
mov ebx, 1
push ecx
mov ecx, evnum
mov edx, 1
int 80h
call nwLine
mov eax, [evnum]
sub eax, '1'
inc eax
add eax, '2'
pop ecx
loop evenLoop
nwLine: ;function to move pointer to next line
mov eax,4 ; System call number(sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx, cr
mov edx, 1
int 80h ; Call the kernel
ret
mov eax,1 ;system call number (sys_exit)
int 80h ;call kernel
section .bss
evnum resb 1
if anyone knows how to solve the problem with the nwLine function, please tell me.
I am trying to read a string from stdin and print it back out using x86, NASM, and Syscalls. Reading in a byte will be a function, and writing out a byte will be a function. I am reading the string from stdin and putting each char into an array. Here is my initial idea:
;read_writer.asm
section .data
arr times 100 db 0 ; array of 100 elements initialzed to 0
ptr dd 0
section .text
global _start
_start:
push ebp ; setup stack
mov ebp, esp ; setup stack
push, 0x10 ; allocate space for potential local variables
call readin: ;call read in func
push eax ;return char from readin will be in eax, push it for writeout
call writeout:
leave
mov eax, 1 ;exit
mov ebx, 0
int 0x80
readin:
push ebp
mov ebp, esp ; setup stack
mov eax, 3 ;read
mov ebx, 1 ;stdin
; i feel like i am missing code here bit not sure what
leave ;reset stack
ret ;return eax
writeout:
push ebp
mov ebp, esp ; setup stack
push eax ;push eax since it was pushed earlier
mov eax, 4 ;write
mov ebx, 1 ;stdout
; i feel like i am missing code here bit not sure what
leave ;reset stack
ret ;return eax
Sample input:
Hello World
Sample output:
Hello World
The functions should be used with cdecl, which I dont think I am doing correctly. I also realised I am not putting the chars into arr.
For starters, you're missing the int 0x80 in both readin and writeout.
And, as you can see here, both sys_read and sys_write expect a (const) char* in ecx. That address should point to the buffer where the bytes to write are stored / the read bytes should be stored.The value of edx should be set to the number of bytes to read / write.
So in the readin example you want something like:
mov eax, 3 ;read
mov ebx, 0 ;stdin. NOTE: stdin is 0, not 1
sub esp,4 ; Allocate some space on the stack
mov ecx,esp ; Read characters to the stack
mov edx,1
int 0x80
movzx eax,byte [esp] ; Place the character in eax, which is used for function return values
add esp,4
And similarly for writeout.
So basically I'm trying to write a hello world program in assembly. The program exits as it should but no string is printed along the way. There are no errors anywhere either. I suspect that I am declaring or using the string wrong somehow.
.intel_syntax noprefix
.data
msg:
.ascii "Hello World"
.text
.globl _start
_start:
mov eax, 4 #call write
mov ebx, 1 #output into stdout
mov ecx, msg #what to write
mov edx, 11 #length of what to write
int 0x80
mov eax, 1 #exit
mov ebx, 0
int 0x80
I have also tried replacing
mov ecx, msg
with
mov ecx, [msg]
but it doesn't seem to make a difference.
You need to use mov ecx, offset msg or lea ecx, msg.
Also make sure you are assembling as 32 bit code in case you are on a 64 bit system.
I am trying to understand the stack in nasm better, so I made this program to try to pass "arguments" to a "function" in nasm. I am very new to this assembly.
section .data
v0s0msg0: db 'Enter something',10
v1t0msg0L: equ $-v0s0msg0
section .bss
v2i0inp0 resb 256
v3v0temp0 resb 256
section .text
global _start
_start:
;This is a nasm program to help me understand the stack better
mov eax,4
mov ebx,1
mov ecx,v0s0msg0
mov edx,v1t0msg0L
int 80h
mov eax,3
mov ebx,0
mov ecx,v2i0inp0
mov edx,256
int 80h
push dword v2i0inp0
call f0m0test0
mov eax,1
mov ebx,0
int 80h
f0m0test0:
pop dword[v3v0temp0]
mov eax,4
mov ebx,1
mov ecx,v3v0temp0
mov edx,256
int 80h
ret 4
I can assemble it, link it, and run it just fine, but when running it, after I enter the input, it just says segmentation fault following two '?' looking characters.
I've tried changing
pop dword[v3v0temp0]
to something like:
pop v3v0temp0
or even:
mov v3v0temp0,dword[ebp]
and many things like that, but they all end up as either segmentation faults, or as an error in the assembler saying:
invalid combination of opcode and operands
I would really appreciate help to make this program work, also, please explain a little bit about the stack, using the prefix 'dword', and what the '[]' characters are for. I would like an explanation just of how to use the stack for "arguments".
I am running this on a linux os, Ubuntu
Thank you in advance
f0m0test0:
pop dword[v3v0temp0]
This pops the return address off the stack, not the parameter.
mov eax,4
mov ebx,1
mov ecx,v3v0temp0
mov edx,256
int 80h
ret 4
Since you've already poped something (though not the intended parameter) off stack, ret 4 above is almost definitely wrong.
I think you want just:
f0m0test0:
mov eax,4
mov ebx,1
mov ecx,[esp+4]
mov edx,256
int 80h
ret 4
Alternatively, instead of the callee cleaning up the parameter with ret 4, have the caller do it (which, I believe, is the usual calling convention):
push dword v2i0inp0
call f0m0test0
add esp,4