section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
Kernel source references:
How does the system know that it has to exit when it read EAX,1 and not EBX,1 ? Since 1 means Sys_Exit.
This comportement is defined in what we call ABI (application binary interface). This should help : What is Application Binary Interface (ABI)?
Related
I'm trying to patch code written in x86 Assembly to an end of the file given as a parameter.
specific in my code:
the function code_start prints a message to stdout.
the function code_end purpose is to patch the code from code_start to the end of a file name given as a parameter from the C program.
My question is:
What should I fill (where I put the question marks) or change in the function code_end in the order it to work as I wish.
My idea was to open the file by an append system call, write the function code_start, close the file.
important note: without using any imported functions, only by using system calls
Code snippet:
code_start:
pushad
mov eax,4 ;system call number (sys_write)
mov ebx,1 ;file descriptor (stdout)
mov ecx, msg ;message to write
mov edx, len ;message length
int 0x80 ;call kernel
popad
ret
code_end:
push ebp ; Save caller state
mov ebp, esp
sub esp, 4 ; Leave space for local var on stack
pushad ; Save some more caller state
mov eax,4 ;system call number (sys_write)
mov ebx, [ebp+8] ; Copy function args to registers: leftmost -> fileName
mov ecx, 1024 ;system call number O_APPEND
int 0x80 ;call kernel
;eax has the pointer to end of file
mov ebx, eax ;move the file pointer to second argument
mov eax, 4 ;move the code of SYS_WRITE
mov ecx, ?? ;from where to write
mov edx, ?? ;how much to write
int 0x80 ;call kernel
mov eax,6 ;system call number (SYS_CLOSE)
mov ebx, [ebp+8] ; Copy function args to registers: leftmost -> fileName
int 0x80 ;call kernel
popad
add esp, 4
pop ebp ; Restore caller state
ret
First of all instead of: mov ecx 1024 it should be mov ecx, 1025 in order to open it for write and appeand.
Second instead of the question marks it should be:
mov ecx, code_start
mov edx code_end
sub edx, code_start
Trying to display the date and it tells me I need a coma after the operand in line 16
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov edx, len ;message length
mov ecx, msg ;message to write
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
dt db __DATE__ ,0xa
len2 equ $ - dt
We've learned only a touch (by touch I mean nothing in class, only theoretical talk of how registers work) of assembly in school and my professor wants us to do something in assembly a little harder than adding two integers. I've been doing a bunch of research and have come up with some code. I am using Microsoft Visual Code on a Linux VM. From my understanding, the code puts input1 into ECX, then puts input2 into ECX, then this essentially appends IF the length of input1 is at least 10 bytes. Not entirely sure how this is working. If I use less than 10 bytes for the first input I get the next input printed on a new line.
I've been trying to understand how [variable] and variable, value vs. address if I understand correctly, fit into this and have played around with reserved byte variables. I'm not asking for my project to be done, but I feel like I'm blindly trying this as opposed to without direction. Thanks in advance guys!
section .text
global main ;must be declared for using gcc
extern printf ;C library used to print
extern exit ;C library used to exit
extern scanf ;C library used to input user entry
main: ;tell linker entry point, called main due to C library usage
;Reads prompt message
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, prompt1 ;message to write called prompt
mov edx, len1 ;message length
int 0x80 ;call kernel
;Accept user input
mov eax, 3 ;system call number (sys_read)
mov ebx, 0 ;file descriptor (stdin)
mov ecx, input1 ;variable to read into, i.e. input
mov edx, 25 ;input length
int 0x80 ;call kernel
;Reads prompt message
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, prompt2 ;message to write called prompt
mov edx, len2 ;message length
int 0x80 ;call kernel
;Accept user input
mov eax, 3 ;system call number (sys_read)
mov ebx, 0 ;file descriptor (stdin)
mov ecx, input2 ;variable to read into, i.e. input
mov edx, 25 ;input length
int 0x80 ;call kernel
;cld
mov al, 0
mov ecx, 50
mov edi, input3
repne scasb
dec edi
mov ecx, 2
mov esi, input4
rep movsb
int 0x80
;Display user input
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, input1 ;message to write
mov edx, 50 ;message length
int 0x80 ;call kernel
call exit
section .data
prompt1 db 'Please enter your first string: ', 0xa ;string to print for user input
len1 equ $ - prompt1 ;length of string prompt
prompt2 db 'Please enter your second string: ',0xa ;string to print for user input
len2 equ $ - prompt2 ;length of string prompt
input3: times 10 db 0 ;variable input is of 10 bytes, null string terminated
input4: times 1 db 0
section .bss
input1 resb 50
input2 resb 25
In DOS Assembly we can do this:
mov dl, 41h
mov ah, 02h
int 21h
But how about Linux nasm x86 Assembly?
section .data
msg db 'H'
len equ $ - msg
section .text
global _start
_start:
mov edx,len
mov ecx,msg
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80
mov eax,1 ;system call number (sys_exit)
int 0x80
Writing a single character may not produce the desired output, because depending on the terminal settings, it may be cached, so you may need to flush the output, to make sure that it appears wherever you write to.
Here is a list of linux 32 Bit system calls.
I want to add two-digit numbers in NASM(Linux). To add two simple numbers, I use the following code:
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax,'3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,sum
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
The result of the code is 7.But when I carry number 17 in register eax forexample the result is not correct.In this case 5.Tell me please what is the problem? Thank you!
Here's your example with a little bit of cleaning up to help make it easier to read.
Suggestion: this kind of consistency will greatly improve your public image.
But hey; nice commenting, I could read your code and understand it (which is why I decided to answer you)
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, '3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx, msg
mov edx, len
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx, sum
mov edx, 1
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
Okay now, as for your comment, "...But when I carry number 17 in register eax forexample the result is not correct."
I can imagine !
Question, when you "...carry number 17 in register eax..." are you doing it like this ?...
Mov Eax,"17"
If so, slow down and take a look at your code one step at a time via debug.
I believe that what you'll see is that you are actually doing this...
Mov Eax, 3137h
Although it might be
Mov Eax, 3731h
Interesting concept. I've never done anything like that. Whatever.
What's more, if you are using this place to store that same number...
sum resb 1
You only have one byte.
Best I can tell, your example code is limited to single digit numbers.
Now then, since your label sum has reserved only one byte; 8 bits, you can see the problem as you are storing 32 bits there. (Well, you're trying to; it won't work.) No clue what happens when you do that. You probably want to rethink that structure.
As for why 17 becomes 5, no clue here.
Let us know if any of this helps you. Assembly is great stuff. As you are personally experiencing, the initial thought adjustment can be strange for the brain, can't it !