Print character using linux x86 assembly and at&t syntax [duplicate] - linux

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.

Related

assembly doesn't print empty line

I just started to learn x86 assembly and I tried to write a simple program that prints all the ascii characters and a line break to the standard output.
It prints everything as expected except the line break and I can't figure out why.
I compiled it with nasm on a 64 bit ubuntu operating system.
Here is the code:
section .data
curr db ' '
section .text
global _start
_start:
next:
;print current character
mov eax,4
mov ebx,1
mov ecx,curr
mov edx,1
int 0x80
;check condition and increment curr
inc byte [curr]
cmp byte [curr],126
jle next
;new line and exit <--- doesn't work ???
mov eax,4
mov ebx,1
mov ecx,10
mov edx,1
int 0x80
mov eax,1
mov ebx,1
int 0x80
The problem is that in that system call, ECX is a pointer, not the character you want to print. Perhaps modifying it like so?
MOV byte [curr], 10
MOV ECX, curr
MOV EAX, 4
MOV EDX, 1
INT 0x80

A loop in assembly doesn't work why?

i have problem. I tried build a loop in assembly (nasm,linux). The loop should "cout" number 0 - 10, but it not work and i don't know why. Here is a code :
section .text
global _start
_start:
xor esi,esi
_ccout:
cmp esi,10
jnl _end
inc esi
mov eax,4
mov ebx,1
mov ecx,esi
mov edx,2
int 80h
jmp _ccout
_end:
mov eax,1
int 80h
section .data
Well, the loop is working, but you aren't using the syscall correctly. There are some magic numbers involved here, so let's get that out of the way first:
4 is the syscall number for write
1 is the file descriptor for the standard output
So far, so good. write requires a file descriptor, the address of a buffer and the length of that buffer or the part of it that it's supposed to write to the file descriptor. So, the way this is supposed to look is similar to
mov eax,4 ; write syscall
mov ebx,1 ; stdout
mov ecx,somewhere_in_memory ; buffer
mov edx,1 ; one byte at a time
compare that to your code:
mov eax,4
mov ebx,1
mov ecx,esi ; <-- particularly here
mov edx,2
int 80h
What you are doing there (apart from passing the wrong length) is passing the contents of esi to write as a memory address from which to read the stuff it's supposed to write to stdout. By pure happenstance this doesn't crash, but there's no useful data at that position in memory.
In order to solve this, you will need a location in memory to put it. Moreover, since write works on characters, not numbers, you'll have to to the formatting yourself by adding '0' (which is 48 in ASCII). All in all, it could look something like this:
section .data
text db 0 ; text is a byte in memory
section .text
global _start
_start:
xor esi,esi
_ccout:
cmp esi,10
jnl _end
inc esi
lea eax,['0'+esi] ; print '0' + esi. lea == load effective address
mov [text],al ; is useful here even though we're not really working on addresses
mov eax,4 ; write
mov ebx,1 ; to fd 1 (stdout)
mov ecx,text ; from address text
mov edx,1 ; 1 byte
int 80h
jmp _ccout
_end:
mov [text],byte 10 ; 10 == newline
mov eax,4 ; write that
mov ebx,1 ; like before.
mov ecx,text
mov edx,1
int 80h
mov eax,1
mov ebx,0
int 80h
The output 123456789: is probably not exactly what you want, but you should be able to take it from here. Exercise for the reader and all that.

add two digit numbers in NASM(Linux)

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 !

Printing variable to command line using assembly in Linux

Trying my hand at Linux assembly and I'm running into the following problem. I'm just starting out so my program is a relatively simple one derived from some examples I found over at linuxassembly. It takes the first argument passed to the command line and prints it out. Here is what I have so far...
section .bss
test_string: resb 3
section .text
global _start
_start:
pop ebx ;argument number
pop ebx ;program name
pop ebx ;first argument
mov [test_string],ebx
mov eax,4
mov ebx,1
mov ecx,test_string
mov edx,3
int 80h
mov eax,1
mov ebx,0
int 80h
I know that this is poorly written, but since I'm new to this, I'm just looking to better understand how assembly instructions/variables work before I move on. I assemble and link using...
nasm -f elf first.asm
ld -m elf_i386 -s -o first first.o
Then I run using..
./first one two
I was thinking that it would print out one but it prints out gibberish like Y*&. What am I doing wrong? Is my test_string the wrong type?
You're trying to print out the value of the pointer to the string instead of printing the string. You want to do this instead.
pop ebx ;argument number
pop ebx ;program name
pop ebx ;pointer to the first argument
mov ecx,ebx ;load the pointer into ecx for the write system call
mov eax,4 ;load the other registers for the write system call
mov ebx,1
mov edx,3
int 80h
mov eax,1
mov ebx,0
int 80h

Nasm program segmentation fault

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

Resources