Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

x86 Assembly Questions

Name: Anonymous 2014-04-26 23:52

$ cat bork.asm

section .data
fuck: dd 0xDEADBEEF

section .text
global _start
_start:
mov dword [fuck],0xABADC0DA

mov eax,1
mov ebx,0
int 0x80


Why doesn't writing to the .data segment segfault? Shouldn't Linux map it to a read-only page?

$ nasm -f elf bork.asm
$ gold -s -o bork-gold bork.asm
$ ld -s -melf_i386 -o bork-ld bork.o
$ du -bh *
432 bork-gold
132 bork.asm
340 bork-ld
608 bork.o


How does such a minimal binary take up 300+ bytes?

Name: Anonymous 2014-04-26 23:56

Please help me learn assembly

I want to use as but I guess ill switch to nasm if it's better. Look I just need a tutorial that teaches me how to program assembly step by step on linux. Please?

Name: Anonymous 2014-04-26 23:59

How does such a minimal binary take up 300+ bytes?

probably the elf header and shit, try objdump -d to see maybe?

Name: Anonymous 2014-04-27 0:05

Name: Anonymous 2014-04-27 0:18

>>2
https://web.archive.org/web/20120822144129/http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html
or if you've never programmed anything in assembly before
https://skilldrick.github.io/easy6502/

>>3
objdump -x bork-ld

bork-ld: file format elf32-i386
bork-ld
architecture: i386, flags 0x00000102:
EXEC_P, D_PAGED
start address 0x08048080

Program Header:
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x00000096 memsz 0x00000096 flags r-x
LOAD off 0x00000098 vaddr 0x08049098 paddr 0x08049098 align 2**12
filesz 0x00000004 memsz 0x00000004 flags rw-

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000016 08048080 08048080 00000080 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000004 08049098 08049098 00000098 2**2
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
no symbols

Name: Anonymous 2014-04-27 0:20

>>5
thanks so much!

Posting my makefile since it was tricky to find the right options


all: 32 64

32:
nasm -f elf hello.s
ld -s -o hello -m elf_i386 hello.o

64:
nasm -f elf64 hello.s
ld -s -o hello hello.o

Name: Anonymous 2014-04-27 0:27

>>5
So according to this, my text and data segments only take up 26 bytes, and the other 314 bytes of my program are in the ELF header. What the fuck.

Also, confirmed that the data segment is writeable. Another what the fuck.

Name: Anonymous 2014-04-27 5:41

>>7
Of course data segment is writeable, as is bss segment. I think data is where your `int g_foo = 42; global variable goes, so you need that to be writeable so your variable is mutable.

Name: Anonymous 2014-04-27 5:46

>>7
A writeable .data segment is the norm. If you want fuck to be immutable, put it in .text or .rodata.

Name: Anonymous 2014-04-27 6:09

>>1
eax
32bit x86 code is obsolete and inefficient.

Name: Anonymous 2014-04-27 6:37

>>1
smallest linux executable is 45 bytes of boilerplate:
http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

smallest DOS exe is just 1 byte

Name: Anonymous 2014-04-27 7:07

>>10
Actually 32 bit code is more efficient because all pointers are half as large; this has a significant effect on code density and instruction cache hit rate. In many cases this outweighs the benefits of the extra general purpose registers that are available in long mode.

Name: Anonymous 2014-04-27 7:17

>>12

Actually real mode is more efficient because all pointers are half as large; this has a significant effect on code density and int 21h cost. In many cases this outweighs the benefits of the extra register width and flat address space that are available in protected mode.

Name: >>12 2014-04-27 7:25

>>11
That's because the DOS COM ``format'' isn't an executable format in any modern sense. DOS just dumped the contents of a .COM file into memory at a fixed address and jumped into it. So you have no dynamic linking, no position independent code, no relocation, nothing. If you want any of that, you need that header ``boilerplate''.

Name: Anonymous 2014-04-27 7:28

>>14
nothing stops COM code from relocating itself.

Name: Anonymous 2014-04-27 7:37

>>13
The functional improvement going from real mode to protected mode is much larger than going from protected mode to long mode. Nearly all modern programs benefit (or even require) memory protection and a 4 GiB virtual address space. Conversely only certain workloads benefit from a 128 TiB virtual address space; for other applications the benefit of sticking with 32 bit pointers in long mode is so large that the Linux kernel supports a whole second 32-bit ABI specifically to allow for it.

Name: Anonymous 2014-04-27 7:40

>>15
It's a pointless exercise to write special purpose loader code for every program that needs to be relocated. The whole point of having a standard executable format is to make it possible for multiple programs to share the same loader.

Name: Anonymous 2014-04-27 7:45

>>17
It's a pointless exercise to write special purpose loader code for every program that needs to be relocated.
That is why we have compiler and static linker. OS kernel shouldn't do anything more than providing hardware abstraction layer. Everything else should be reconfigurable.

Name: Anonymous 2014-04-27 7:53

>>18
When did this become an operating systems discussion?

You are free to reinvent the wheel for every program you write. However I imagine after you've written the same dumb boilerplate loader code for three or four programs I imagine you will end up rearranging the combined result into something that looks a lot like loaders others have already written.

Name: >>19 2014-04-27 8:10

>>18
Also, as a side note - dynamic linkers need not be part of the kernel, and in practice they often are not. On Linux systems the dynamic linkers are just libraries can indeed be replaced.

Name: Anonymous 2014-04-27 8:25

>>19

Works just as okey. For example, Windows 3.1 provided it's own linker.

Name: Anonymous 2014-04-27 9:56

>>8,9
Ah, ok. I relocated fuck to .rodata and bork segfaulted as expected.
I also objdump -x'd this program and confirmed that it sticks the string in .rodata:

#include <stdio.h>
int main(int argc, char **argv) {
puts("EXPERT PROGRAMMER");
return 0;
}


That doesn't explain why it takes 6 fucking kilobytes to poop a constrant string onto stdout, but whatever.

>>11
Thanks for the read. Sticking the whole program inside the ELF header, that's funny.

Name: Anonymous 2014-04-27 11:22

>>11
DOS exe
*com

Name: Anonymous 2014-04-27 11:24

it sticks the string in .rodata
Of course it does. C string literals are const.

Name: Anonymous 2014-04-27 13:33

>>22

Now it's only 4kb.


#include <unistd.h>

int main(int argc, char** argv) {
write(STDOUT_FILENO, "EXPERT PROGRAMMER", 17);
return 0;
}

Name: Anonymous 2014-04-27 15:03

>>25
section .rodata
expert: db "EXPERT PROGRAMMER"

section .text
global _start
_start:
; afaik most registers are zeroed at start
mov al,4 ; write syscall
inc ebx ; fd = 1, aka stdout
mov ecx,expert ; str ptr
mov dl,17 ; str len
int 0x80

mov al,1 ; exit syscall
xor ebx,ebx ; error code = 0
int 0x80

$ du -b expert
320

$ size expert
text data bss dec hex filename
35 0 0 35 23 expert

$ objdump -d expert
expert: file format elf32-i386

Disassembly of section .text:

08048060 <.text>:
8048060: b0 04 mov al,0x4
8048062: 43 inc ebx
8048063: b9 74 80 04 08 mov ecx,0x8048074
8048068: b2 11 mov dl,0x11
804806a: cd 80 int 0x80
804806c: b0 01 mov al,0x1
804806e: 31 db xor ebx,ebx
8048070: cd 80 int 0x80


OMG OPTIMIZED

Name: Anonymous 2014-04-27 17:51

>>10
what is it obsolete by you dick head

Name: Anonymous 2014-04-27 18:31

I've impreoved hte program and made it more exciting


section .rodata
expert: db "LPOL"

section .text
global _start
_start:
mov al,4 ; write syscall
xor ebx,ebx
inc ebx ; fd = 1, aka stdout
mov ecx,expert ; str ptr
mov dl,4 ; str len
int 0x80

jmp _start

Name: Anonymous 2014-04-27 18:53

i miss dos

Name: Anonymous 2014-04-27 18:57

prints out a pyramid of stars... what should I prorgam next?

>>29
try dosbos, it can emulate IPX

section .rodata
expert: db "*"
nl: db 0Ah

section .text
global _start
_start:
mov edi,0
.loop:
inc edi
mov esi,edi
call stars
call newline
jmp .loop

mov al,1 ; exit syscall
xor ebx,ebx ; error code = 0
int 0x80

stars:
call star
dec esi
cmp esi,0
jne stars
ret

star: mov al,4
mov ebx,1
mov ecx,expert
mov dl,1 ; length
int 0x80
ret

newline:
mov al,4
mov ebx,1
mov ecx,nl
mov dl,1 ; length
int 0x80
ret

;; *
;; **
;; ***
;; ****
;; *****
;; ******
;; *******
;; ********
;; *********
;; **********
;; ***********
;; ************
;; *************
;; **************
;; ***************
;; ****************
;; *****************

Name: Anonymous 2014-04-27 19:39

Name: Anonymous 2014-04-27 20:36

made it look up an array to know what length each line is


section .rqodata
expert: db "*"
nl: db 0Ah
mr_arr: dd 2,3,4,4,4,2,2,3,4,0

section .text
global _start
_start:
xor edi,edi
loop:
xor esi,esi
mov si,[mr_arr + 4*edi]
cmp esi,0
je done
call stars
call newline
inc edi
jmp loop

done:
mov al,1 ; exit syscall
xor ebx,ebx ; error code = 0
int 0x80

stars:
call star
dec esi
cmp esi,0
jne stars
ret

star: mov al,4
mov ebx,1
mov ecx,expert
mov dl,1 ; length
int 0x80
ret

newline:
mov al,4
mov ebx,1
mov ecx,nl
mov dl,1 ; length
int 0x80
ret

;; **
;; ***
;; ****
;; ****
;; ****
;; **
;; **
;; ***
;; ****

Name: Anonymous 2014-04-28 22:52

any tips of learning x86

Name: Anonymous 2014-04-28 23:04

>>33
You need to be careful that you only use each segment for its intended use. The text segment (.text) can contain both code and data (keeping in mind that any data you place in the text segment cannot be changed by your program during execution). The initialized part of the data segment (.data) should contain just data, not code. And the uninitialized part of the data segment (.bss) cannot have values placed in it as assembly time at all -- all you can do here is allocate memory (that is, add to the total amount of memory to be included as uninitialized data). In all three types of segment, you can define symbolic labels; such a label has as its value an address within that segment.

Name: Anonymous 2014-04-28 23:48

I managed to call a c function today using the host c file:

void foo(void);
void main(void) {
foo();
}

// $ nasm -f elf primes.s
// $ gcc -m32 primes.o host.c
// $ ./a.out
// hello world


and the assembly code:


extern puts
section .data
msg db "hello world",0

section .text
global foo
foo:
push ebp ; save ebp onto the stack
mov ebp,esp ; save the stack pointer in ebp
push msg ; push argument onto the stack
call puts
add esp,4 ; skip past 'msg' on the stack
mov esp,ebp ; reset the stack???
pop ebp ; restore ebp

mov eax,1 ; sys_exit
mov ebx,0 ; 0
int 0x80


not totally sure its correct.. and I'd like to do it without a .c file

Name: Anonymous 2014-04-29 0:06

>>34
Fuck you, I make a new segment for every function I need and it's never bitten me in the ass.

Who cares about Windows asm any more anyway. Is it because AT&T syntax is such ugly garbage? Yeah, GCC made a blunder choosing that one.

Also, FASM is better than nasm.

Name: Anonymous 2014-04-29 0:15

>>36
FASM is the CL of assemblers, that is, for niggers

Name: Anonymous 2014-04-29 0:49

>>36
Is it because AT&T syntax is such ugly garbage? Yeah, GCC made a blunder choosing that one.
GCC allows you to select between Intel and AT&T syntax, same goes for GAS

FASM
Hipster shit, think of ruby or python

Name: Anonymous 2014-04-29 1:28

>>38
What assembler is better than FASM? And what the fuck do you mean by ``hipster''? You could say ``normalfag'' as fucking every ``normal'' person uses ruby or python.

Name: Anonymous 2014-04-29 10:49

>>38 i think you're stuck with at&t syntax for inline asm though

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List