You are not logged in.
Pages: 1
Awhile back, I couldn't figure out assembly, I even made a post somewhere around here asking for help with retrieving argc. Anyhow, I made a few programs in assembly and the one I am proud would be simple in any other language, like 5 lines in C I think, but in assembly, it was about 45 lines, haha. So I feel like sharing it.
.section .data
.section .bss
.equ SIZE, 1
.lcomm BUFFER, SIZE
.section .text
.globl _start
_start:
open:
movl $5, %eax # open() system call
movl 8(%esp), %ebx # first argument
movl $0, %ecx # intended for reading
movl $0666, %edx # permission
int $0x80
read:
movl %eax, %ebx # store fd for read()
movl $3, %eax # read() system call
movl $BUFFER, %ecx # store buffer address
movl $SIZE, %edx # buffer size
int $0x80
cmpl $0, %eax # EOF
jle close # close
display:
movl %ebx, %ebp # store fd into %ebp
movl $4, %eax # write() system call
movl $1, %ebx # fd STDOUT
int $0x80
movl %ebp, %eax # move fd into %eax
jmp read # continue reading
close:
movl $6, %eax # close() system call
movl %ebp, %ebx # move fd back into %ebx
int $0x80
exit:
movl $1, %eax # exit() system call
xorl %ebx, %ebx # return 0
int $0x80
Beautiful. I actually commented this too. Anyhow, hate, rate, or so on. By the way, AT&T syntax > Intel. I used to program in Perl. :s
Last edited by Aprz (2009-04-17 08:02:38)
Offline
Here is my cat, supporting fancy stuff such as multiple arguments, or reading from stdin.
I wrote it ages ago, so I'm not sure I can answer any questions
It should be portable across unices ( ) since it uses a set of macros (not mine) for system calls and such. The strlen part is also not mine. Btw, intel syntax
Also, it's full of bugs, for example when printing error messages. Fun all around.
%include "system.inc"
%assign BUFSIZE 0x2000
DATASEG
openerrmsg: db 'Error opening file '
openerrlen: equ $-openerrmsg
readerrmsg: db 'Error reading file.'
readerrlen: equ $-readerrmsg
newline: db 0xa
newlinelen: equ $-newline
UDATASEG
buf resb BUFSIZE
CODESEG
START:
pop ebp ; number of arguments
pop eax ; program name (argv)
dec ebp ; we dont care about the program name
cmp ebp, 0
jle read_stdin ;no file names
jmp next_file
next_file: ;check for more files in argv
;moves file name * to ebx, or exits
cmp ebp, 0
jle exit_done
pop ebx ; move to next element in argv
dec ebp ; decrement number of args
read_file:
sys_open ebx, O_RDONLY ; open file for reading
cmp eax, -1 ;check for error during open call
jle open_error ;print error and die
call read_loop ;read FD in eax
jmp next_file ;check for more files
exit_done:
sys_exit 0
; file name we could not open is in ebx
open_error:
sys_write STDERR, openerrmsg, openerrlen
mov eax, ebx ;pointer to file name
call strlen
sys_write STDERR, [ebx], eax
sys_write STDERR, newline, newlinelen
sys_exit 1
read_stdin:
mov eax,STDIN
call read_loop
sys_exit 0
;reads fd in eax
;prints to stdout
read_loop:
mov edi, eax
begin_read:
sys_read edi, buf, BUFSIZE
cmp eax, 0
je escape_loop
jl read_error
sys_write STDOUT, buf, eax
jmp begin_read
escape_loop:
ret
;
read_error:
sys_write STDERR, readerrmsg, readerrlen
sys_write STDERR, newline, newlinelen
sys_exit 1
;finds the length of the string pointed to by eax.
;stores result in eax
;touches ecx, al and edi
strlen:
mov edi, eax ;string pointer in edi
sub ecx, ecx ;clear out ecx
sub al, al ;clear out al
not ecx ;ecx = -1, or 2^32
;counts number of bytes before we find the value
;pointed to by al (0)
cld
repne scasb
;use two's complement logic to find the number of bytes
;the number of bytes is equal to (ecx*-1)-2
;could be written as
;neg ecx
;dec ecx
;dec ecx
not ecx
dec ecx
;per contract, store result in eax
mov eax, ecx
ret
; end strlen
Offline
display:
movl %ebx, %ebp # store fd into %ebp
Is there a specific reason why you use ebp to store a value?
ebp should contain the stack frame's base-adress. So using it for different purposes may (and probably will) create problems when using function calls that create a new stack frame on top of the current frame.
Offline
No real reason that I could think of, just temporary storage that was easier than having to move more values around, which I figured would slow it down.
Offline
Arpz, what was the assembler you used? I was looking to get into assembly language programming, but I heard that gas isn't the best tool to use.
Offline
Arpz, what was the assembler you used? I was looking to get into assembly language programming, but I heard that gas isn't the best tool to use.
What he wrote is AT&T syntax so he probably uses good 'ol `as` (from binutils)
AT&T is not preety for some, but I myself find it really sexy looking . There's not a whole lot of difference between intel and AT&T so don't worry...
What makes AT&T "better" is the fact that dissasembling with gdb or whatever outputs using this syntax..so it's a bit of a plus to understand it
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
What makes AT&T "better" is the fact that dissasembling with gdb or whatever outputs using this syntax..so it's a bit of a plus to understand it
This is a point that would make me consider switching. But other than that I prefer Intel syntax just because I think it looks nicer. I use nasm.
Disclaimer: I'm an assembly n00b, but I'm learning slowly. It's ridiculously fun
Offline
Wra!th wrote:What makes AT&T "better" is the fact that dissasembling with gdb or whatever outputs using this syntax..so it's a bit of a plus to understand it
Disclaimer: I'm an assembly n00b, but I'm learning slowly. It's ridiculously fun
Fun but useless (unless you're planning on doing some hardcore device drivers, some exploits, or..why not..an OS...)
I left asm way behind..it's not worth the time spent
Last edited by Wra!th (2009-04-23 05:36:13)
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
Fun but useless (unless you're planning on doing some hardcore device drivers, some exploits, or..why not..an OS...)
I left asm way behind..it's not worth the time spent
Well I'm not sure about device drivers, but exploits and low level OS code intrigue me, so why not
Also, I've been playing with KolibriOS a little lately, which for those of you unaware is an OS written entirely in assembly, but that is getting a little off topic
Offline
Yes, I used GAS.
Computer science and programming is what I study and do for entertainment and that's its only use to me, haha, I am training to be EMT-1 (hopefully a paramedic later on) right now so I doubt I'll be using Linux to do CPR or anything like that, haha. I heard assembly was a lot of fun so I decided to learn it. What really got me started on assembly though was my friend started doing assembly for NASM. Another friend was forced to take a class on MASM for his computer science degree. I decided to be different and use GAS. The greatest benefit with GAS for me though was because I already had GCC that meant I already had GAS which is why I chose GAS, haha.
If you can write in AT&T syntax, you can write in Intel, vise versa. It's not hard to convert. I'd say that if I had a favorite though, it would still be AT&T because I find the prefixes a very nice way to represent your coding(which is one reason why I like programming in Perl too - I mainly program in assembly or C though) such as $ meaning it is a value, a % being the registers, and even though I program in C with "int i = 0" as in location = value, I think of things more like "cp /old/path/ /new/path/" which is funny because that's actually how the whole value things works in assembly, you copy it, haha, even though that's not a programming example, that's exactly how I think of it.
Oh, I forgot to say that another reason I wanted to learn assembly was because I am reading about the Linux kernel in "Understanding the Linux Kernel Edition 3" and the first coding snipplets it gives is in assembly.
My goal with C and x86 Assembly is to rebuild parts my operating system hence why I made the shell which was a very important first step for me in my opinion. Open source is mostly useless if you can't program and it's a lot of fun to use stuff that you make. Even though my shell has no tab completion, I still use it, and it urges myself to add that feature in, haha.
Last edited by Aprz (2009-04-23 07:13:27)
Offline
I loved that post Aprz, especially the last two paragraphs, it fits me very well.
I love learning for the sake of learning, but being able to program at any level is a very useful skill, even if you use Windows (maybe even _especially_ if you use Windows). Being able to code up small hacks or apps to help you be productive is the coolest thing ever in my opinion, and does give a huge sense of satisfaction
I suppose this does apply more in the open source world, if you find something that you don't quite like about an application, you can just grab the source and modify it. In fact, I find the hardest part about doing that is often getting the source to compile in the first place, rather than making the changes to it
Last edited by HashBox (2009-04-23 09:22:07)
Offline
I still have a soft spot for assembler, though I don't use it much. I don't think it's at all useless. At the very least it's a great learning exercise which can lead to deeper understanding of lots of things. The program stack, dynamic linking, ELF file structure, etc in the software direction. Hardware interrupts, cycles, threading, input/output in the hardware/computer architecture direction. Etc, etc... There are still practical uses. Like reverse engineering, for malware anaylsis, or embedded microcontrollers, which are in almost everything now... maybe you could program your own defibrillator
Anyways, I had played with your cat program, to learn AT&T syntax and try using POPAD for the first time:
# EDI must be set to 0
.macro stack_args A, B, C, D
PUSHL $\A # EAX
PUSHL $\C # ECX
PUSHL $\D # EDX
PUSHL \B # EBX
PUSHL %EDI # ESP (ignored)
PUSHL %EDI # EBP
PUSHL %ESI # ESI (keep our input fileno)
PUSHL %EDI # EDI
.endm
.section .bss
.equ buffer_max, 1024
.lcomm buffer, buffer_max
.section .text
.globl _start
_start:
POP %ECX # error if no arguments given
DEC %ECX
JZ error
POP %EAX
POP %EAX
stack_args 5, %EAX, 0, 0666
POPAL
INT $0x80 # syscall open()
TEST %EAX, %EAX
JS error # exit if open returns -1
MOVL %EAX, %ESI # store fileno in ESI
XORL %EAX, %EAX
INCL %EAX # creates args for read() on stack
stack_args 4, %EAX, buffer, buffer_max
# creates args for write() on stack
stack_args 3, %ESI, buffer, buffer_max
readprint_loop:
POPAL
INT $0x80 # syscall read()
TEST %EAX, %EAX
JS error # error if returned < 0
JZ close # close if 0 bytes were left
MOVL %EAX, 4*5(%ESP) # store bytes read into write's args
POPAL
INT $0x80 # syscall write()
TEST %EAX, %EAX
JS error # error if returned <= 0
JZ error
SUBL $64, %ESP # rewind ESP to read's args
JMP readprint_loop
close:
MOVL $6, %EAX # close() system call
# move fd back into %ebx
MOVL %ESI, %EBX
INT $0x80
XORL %EBX, %EBX # return 0
exit:
MOVL $1, %EAX # exit() system call
INT $0x80
error:
XORL %EBX, %EBX
INC %EBX
JMP exit
I had hoped it would be smaller but its 36 bytes bigger at a wopping 416 bytes! Oh dear! I mostly program perl now, and I see what you mean with the sigils! I like it. The one thing where AT&T is worse is with the memory addressing... ugly.
Offline
Nice! I like it
Offline
Hehe found some stuff I did a while back
A 31 byte demo of a 'tv' lost signal thingy (16 bit...dos..)
format binary as 'com'
org 100h
start: mov al, 12h
int 10h
push word 0xA000
pop es
L1: mov di, es
mov dl, 200
L2: mov cx, 320
L3: movsb
loop L3
in al, 060h
cmp al, 01
je exit
dec dl
jz L1
jmp L2
exit: ret
Frolic!
format binary as 'com'
org 0x100
main: mov ax, 0x0013 ; MODE 13 Graphics
int 10h
push word 0xA000; 0xA000 == begin of video mem
pop es ; set es to point to the video memory
L1: mov ax, 0
L2: mov cx, 64000 ; 320*200
repz stosb
push ax ; preserve ax
in al, 060h ; get keyboard
cmp al, 01 ; is ESCAPE?
je exit ; exit if yes
pop ax ; restore ax
inc ax
cmp ax, 7
je L1
jmp L2
exit: mov ax, 0x004C ; exit with error code 0
int 21h
Linux hardcoded ELF, writes hello, world to file: compiles to about 144 bytes
BITS 32
org 0x08048000
ehdr:
db 0x7F, "ELF", 1, 1, 1
times 9 db 0
dw 2
dw 3
dd 1
dd _start
dd phdr - $$
dd 0
dd 0
dw ehdrsz
dw phdrsz
dw 1
dw 0
dw 0
dw 0
ehdrsz equ $ - ehdr
phdr:
dd 1
dd 0
dd $$
dd $$
dd filesz
dd filesz
dd 5
dd 0x1000
phdrsz equ $ - phdr
_start:
mov ebx, fnm
mov eax, 8; create file
mov ecx, 00644Q; got it from some tut..ecx has to hold the file persmisions..that octal = RW RW RW
int 80h
mov ebx, eax;eax holds the file descriptor got from "create()"
mov eax, 4; write
mov ecx, msg
mov edx, msz
int 80h
mov eax, 6; close file
int 80h
xor eax, eax
inc eax
xor ebx, ebx
int 80h
filesz equ $ - $$
section .data
msg: db "Hello, world!", 10
msz: equ $ - msg
fnm : db "file.txt"
ebx@ebx-desktop:~$ nasm -f bin tinywrite.asm -o tinywrite
ebx@ebx-desktop:~$ chmod +x tinywrite
ebx@ebx-desktop:~$ strip -s -X -R .comment -R .bss tinywrite
ebx@ebx-desktop:~$ wc -c tinywrite
144 tinywrite
I wrote these 2 years ago...don't expect to be much...
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
I think I'll have to get a dosbox or something set up and have a play with this
Offline
Ah, the programming section rocks compare to the rest of the Arch forums, haha. Everywhere else I post, they all treat me like a noob. "Aprz, this is how you compile a kernel". Annoys me. I know they can't tell I know from looks, but they jump straight to conclusion or just flat out say stupid things. Just want to say you guys rock (and the folks who posted in my shell post mostly, but I didn't like some of the post in there). I take things too personally. I need to write something else in assembly so I can feel cool again.
Last edited by Aprz (2009-04-23 15:02:04)
Offline
but I didn't like some of the post in there)
10 bucks say that reffers to my posts
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
You're good. I forgot you were the one who said that, haha. Are you sure it is using bash. I mean, that's why I used fork() to create a process and then use that with execvp() as you see in the source. I have tried it without initiating bash, but I still kept bash for the init scripts since my shell cannot handle that yet. I swear that what you're thinking that would be using the shell is system(), not the exec() family.
I would be sad if I am totally wrong, but I am up for learning.
Last edited by Aprz (2009-04-24 08:16:26)
Offline
You're good. I forgot you were the one who said that, haha. Are you sure it is using bash. I mean, that's why I used fork() to create a process and then use that with execvp() as you see in the source. I have tried it without initiating bash, but I still kept bash for the init scripts since my shell cannot handle that yet. I swear that what you're thinking that would be using the shell is system(), not the exec() family.
I would be sad if I am totally wrong, but I am up for learning.
Not I didn't say it's exactly like running system(). haven't used fork much so I could be awfully wrong
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
In response to the AT&T/intel debate - newer GDB can be made to show intel syntax.
Just
set disassembly-flavor intel
Offline
In response to the AT&T/intel debate - newer GDB can be made to show intel syntax.
Just
set disassembly-flavor intel
Blasphemy!
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
AT&T syntax still rocks my socks. \o/
Offline
Hey -- feel free to hate on intel syntax. Just don't bring up GDB support as a point in favour of AT&T
Offline
Pages: 1