I wrote a very simple C code as follow:
int data_items[] = {3,67,32,4,89,6,34,2,9,0};
int max(int* pt)
{
int val = *pt;
while(*pt != 0)
{
if (*pt > val)
{
val = *pt;
}
++pt;
}
return val;
}
int main()
{
max(data_items);
return 0;
}
then I compiled it with gcc:
gcc main.c
and then disassembled it with:
objdump -d a.out
At last I get the assemble code:
a.out: file format elf64-x86-64
Disassembly of section .init:
00000000004003a8 <_init>:
4003a8: 48 83 ec 08 sub $0x8,%rsp
4003ac: 48 8b 05 45 0c 20 00 mov 0x200c45(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0>
4003b3: 48 85 c0 test %rax,%rax
4003b6: 74 05 je 4003bd <_init+0x15>
4003b8: e8 33 00 00 00 callq 4003f0 <__gmon_start__#plt>
4003bd: 48 83 c4 08 add $0x8,%rsp
4003c1: c3 retq
Disassembly of section .plt:
00000000004003d0 <__libc_start_main#plt-0x10>:
4003d0: ff 35 32 0c 20 00 pushq 0x200c32(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
4003d6: ff 25 34 0c 20 00 jmpq *0x200c34(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
4003dc: 0f 1f 40 00 nopl 0x0(%rax)
00000000004003e0 <__libc_start_main#plt>:
4003e0: ff 25 32 0c 20 00 jmpq *0x200c32(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
4003e6: 68 00 00 00 00 pushq $0x0
4003eb: e9 e0 ff ff ff jmpq 4003d0 <_init+0x28>
00000000004003f0 <__gmon_start__#plt>:
4003f0: ff 25 2a 0c 20 00 jmpq *0x200c2a(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
4003f6: 68 01 00 00 00 pushq $0x1
4003fb: e9 d0 ff ff ff jmpq 4003d0 <_init+0x28>
Disassembly of section .text:
0000000000400400 <_start>:
400400: 31 ed xor %ebp,%ebp
400402: 49 89 d1 mov %rdx,%r9
400405: 5e pop %rsi
400406: 48 89 e2 mov %rsp,%rdx
400409: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40040d: 50 push %rax
40040e: 54 push %rsp
40040f: 49 c7 c0 b0 05 40 00 mov $0x4005b0,%r8
400416: 48 c7 c1 40 05 40 00 mov $0x400540,%rcx
40041d: 48 c7 c7 28 05 40 00 mov $0x400528,%rdi
400424: e8 b7 ff ff ff callq 4003e0 <__libc_start_main#plt>
400429: f4 hlt
40042a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400430 <deregister_tm_clones>:
400430: b8 8f 10 60 00 mov $0x60108f,%eax
400435: 55 push %rbp
400436: 48 2d 88 10 60 00 sub $0x601088,%rax
40043c: 48 83 f8 0e cmp $0xe,%rax
400440: 48 89 e5 mov %rsp,%rbp
400443: 77 02 ja 400447 <deregister_tm_clones+0x17>
400445: 5d pop %rbp
400446: c3 retq
400447: b8 00 00 00 00 mov $0x0,%eax
40044c: 48 85 c0 test %rax,%rax
40044f: 74 f4 je 400445 <deregister_tm_clones+0x15>
400451: 5d pop %rbp
400452: bf 88 10 60 00 mov $0x601088,%edi
400457: ff e0 jmpq *%rax
400459: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
0000000000400460 <register_tm_clones>:
400460: b8 88 10 60 00 mov $0x601088,%eax
400465: 55 push %rbp
400466: 48 2d 88 10 60 00 sub $0x601088,%rax
40046c: 48 c1 f8 03 sar $0x3,%rax
400470: 48 89 e5 mov %rsp,%rbp
400473: 48 89 c2 mov %rax,%rdx
400476: 48 c1 ea 3f shr $0x3f,%rdx
40047a: 48 01 d0 add %rdx,%rax
40047d: 48 d1 f8 sar %rax
400480: 75 02 jne 400484 <register_tm_clones+0x24>
400482: 5d pop %rbp
400483: c3 retq
400484: ba 00 00 00 00 mov $0x0,%edx
400489: 48 85 d2 test %rdx,%rdx
40048c: 74 f4 je 400482 <register_tm_clones+0x22>
40048e: 5d pop %rbp
40048f: 48 89 c6 mov %rax,%rsi
400492: bf 88 10 60 00 mov $0x601088,%edi
400497: ff e2 jmpq *%rdx
400499: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000004004a0 <__do_global_dtors_aux>:
4004a0: 80 3d e1 0b 20 00 00 cmpb $0x0,0x200be1(%rip) # 601088 <__TMC_END__>
4004a7: 75 11 jne 4004ba <__do_global_dtors_aux+0x1a>
4004a9: 55 push %rbp
4004aa: 48 89 e5 mov %rsp,%rbp
4004ad: e8 7e ff ff ff callq 400430 <deregister_tm_clones>
4004b2: 5d pop %rbp
4004b3: c6 05 ce 0b 20 00 01 movb $0x1,0x200bce(%rip) # 601088 <__TMC_END__>
4004ba: f3 c3 repz retq
4004bc: 0f 1f 40 00 nopl 0x0(%rax)
00000000004004c0 <frame_dummy>:
4004c0: 48 83 3d 58 09 20 00 cmpq $0x0,0x200958(%rip) # 600e20 <__JCR_END__>
4004c7: 00
4004c8: 74 1e je 4004e8 <frame_dummy+0x28>
4004ca: b8 00 00 00 00 mov $0x0,%eax
4004cf: 48 85 c0 test %rax,%rax
4004d2: 74 14 je 4004e8 <frame_dummy+0x28>
4004d4: 55 push %rbp
4004d5: bf 20 0e 60 00 mov $0x600e20,%edi
4004da: 48 89 e5 mov %rsp,%rbp
4004dd: ff d0 callq *%rax
4004df: 5d pop %rbp
4004e0: e9 7b ff ff ff jmpq 400460 <register_tm_clones>
4004e5: 0f 1f 00 nopl (%rax)
4004e8: e9 73 ff ff ff jmpq 400460 <register_tm_clones>
00000000004004ed <max>:
4004ed: 55 push %rbp
4004ee: 48 89 e5 mov %rsp,%rbp
4004f1: 48 89 7d e8 mov %rdi,-0x18(%rbp)
4004f5: 48 8b 45 e8 mov -0x18(%rbp),%rax
4004f9: 8b 00 mov (%rax),%eax
4004fb: 89 45 fc mov %eax,-0x4(%rbp)
4004fe: eb 19 jmp 400519 <max+0x2c>
400500: 48 8b 45 e8 mov -0x18(%rbp),%rax
400504: 8b 00 mov (%rax),%eax
400506: 3b 45 fc cmp -0x4(%rbp),%eax
400509: 7e 09 jle 400514 <max+0x27>
40050b: 48 8b 45 e8 mov -0x18(%rbp),%rax
40050f: 8b 00 mov (%rax),%eax
400511: 89 45 fc mov %eax,-0x4(%rbp)
400514: 48 83 45 e8 04 addq $0x4,-0x18(%rbp)
400519: 48 8b 45 e8 mov -0x18(%rbp),%rax
40051d: 8b 00 mov (%rax),%eax
40051f: 85 c0 test %eax,%eax
400521: 75 dd jne 400500 <max+0x13>
400523: 8b 45 fc mov -0x4(%rbp),%eax
400526: 5d pop %rbp
400527: c3 retq
0000000000400528 <main>:
400528: 55 push %rbp
400529: 48 89 e5 mov %rsp,%rbp
40052c: bf 60 10 60 00 mov $0x601060,%edi
400531: e8 b7 ff ff ff callq 4004ed <max>
400536: b8 00 00 00 00 mov $0x0,%eax
40053b: 5d pop %rbp
40053c: c3 retq
40053d: 0f 1f 00 nopl (%rax)
0000000000400540 <__libc_csu_init>:
400540: 41 57 push %r15
400542: 41 89 ff mov %edi,%r15d
400545: 41 56 push %r14
400547: 49 89 f6 mov %rsi,%r14
40054a: 41 55 push %r13
40054c: 49 89 d5 mov %rdx,%r13
40054f: 41 54 push %r12
400551: 4c 8d 25 b8 08 20 00 lea 0x2008b8(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>
400558: 55 push %rbp
400559: 48 8d 2d b8 08 20 00 lea 0x2008b8(%rip),%rbp # 600e18 <__init_array_end>
400560: 53 push %rbx
400561: 4c 29 e5 sub %r12,%rbp
400564: 31 db xor %ebx,%ebx
400566: 48 c1 fd 03 sar $0x3,%rbp
40056a: 48 83 ec 08 sub $0x8,%rsp
40056e: e8 35 fe ff ff callq 4003a8 <_init>
400573: 48 85 ed test %rbp,%rbp
400576: 74 1e je 400596 <__libc_csu_init+0x56>
400578: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
40057f: 00
400580: 4c 89 ea mov %r13,%rdx
400583: 4c 89 f6 mov %r14,%rsi
400586: 44 89 ff mov %r15d,%edi
400589: 41 ff 14 dc callq *(%r12,%rbx,8)
40058d: 48 83 c3 01 add $0x1,%rbx
400591: 48 39 eb cmp %rbp,%rbx
400594: 75 ea jne 400580 <__libc_csu_init+0x40>
400596: 48 83 c4 08 add $0x8,%rsp
40059a: 5b pop %rbx
40059b: 5d pop %rbp
40059c: 41 5c pop %r12
40059e: 41 5d pop %r13
4005a0: 41 5e pop %r14
4005a2: 41 5f pop %r15
4005a4: c3 retq
4005a5: 66 66 2e 0f 1f 84 00 data32 nopw %cs:0x0(%rax,%rax,1)
4005ac: 00 00 00 00
00000000004005b0 <__libc_csu_fini>:
4005b0: f3 c3 repz retq
Disassembly of section .fini:
00000000004005b4 <_fini>:
4005b4: 48 83 ec 08 sub $0x8,%rsp
4005b8: 48 83 c4 08 add $0x8,%rsp
4005bc: c3 retq
My question is that, in main function:
40052c: bf 60 10 60 00 mov $0x601060,%edi
the address $0x601060 should be the address of the array data_items in the C code. But I can not find the data_items array value in the assemble code, where is it?
By the way, in the max function code:
4004f1: 48 89 7d e8 mov %rdi,-0x18(%rbp)
I do think the stack should be:
mov %rdi, -0x8(%rbp)
why the compiler makes some hole in the stack?
my system is Ubuntu 14.04 LTS.
objdump -d only disassembles sections of the executable where there's supposed to be code.
Use objdump -D to disassemble all sections, and you'll find this:
Disassembly of section .data:
08049760 <__data_start>:
...
08049780 <data_items>:
8049780: 03 00 add (%eax),%eax
8049782: 00 00 add %al,(%eax)
8049784: 43 inc %ebx
8049785: 00 00 add %al,(%eax)
8049787: 00 20 add %ah,(%eax)
8049789: 00 00 add %al,(%eax)
804978b: 00 04 00 add %al,(%eax,%eax,1)
804978e: 00 00 add %al,(%eax)
That's your array. objdump will try to disassemble it as if it was machine code, so the assembly isn't going to make sense though).
If you run nm a.out, you will see that 0x601060 is the address of data_items.
When it comes to runtime dissasembly gdb itself can be very handy:
(gdb) break main
Breakpoint 1 at 0x4004f3
(gdb) break max
Breakpoint 2 at 0x4004b8
(gdb) run
Starting program: /home/dtarcatu/workspace/ctest/a.out
Breakpoint 1, 0x00000000004004f3 in main ()
(gdb) disas
Dump of assembler code for function main:
0x00000000004004ef <+0>: push %rbp
0x00000000004004f0 <+1>: mov %rsp,%rbp
=> 0x00000000004004f3 <+4>: mov $0x601040,%edi
0x00000000004004f8 <+9>: callq 0x4004b4 <max>
0x00000000004004fd <+14>: mov $0x0,%eax
0x0000000000400502 <+19>: pop %rbp
0x0000000000400503 <+20>: retq
End of assembler dump.
(gdb) x 0x601040
0x601040 <data_items>: 0x00000003
(gdb) x /10d 0x601040
0x601040 <data_items>: 3 67 32 4
0x601050 <data_items+16>: 89 6 34 2
0x601060 <data_items+32>: 9 0
Now regarding your stack discipline dillema I'm not sure I can come up with a very good answer, but I think it's related to the x86-64 red zone optimization.
(gdb) c
Continuing.
Breakpoint 2, 0x00000000004004b8 in max ()
(gdb) disas
Dump of assembler code for function max:
0x00000000004004b4 <+0>: push %rbp
0x00000000004004b5 <+1>: mov %rsp,%rbp
=> 0x00000000004004b8 <+4>: mov %rdi,-0x18(%rbp)
0x00000000004004bc <+8>: mov -0x18(%rbp),%rax
0x00000000004004c0 <+12>: mov (%rax),%eax
0x00000000004004c2 <+14>: mov %eax,-0x4(%rbp)
0x00000000004004c5 <+17>: jmp 0x4004e0 <max+44>
0x00000000004004c7 <+19>: mov -0x18(%rbp),%rax
0x00000000004004cb <+23>: mov (%rax),%eax
0x00000000004004cd <+25>: cmp -0x4(%rbp),%eax
0x00000000004004d0 <+28>: jle 0x4004db <max+39>
0x00000000004004d2 <+30>: mov -0x18(%rbp),%rax
0x00000000004004d6 <+34>: mov (%rax),%eax
0x00000000004004d8 <+36>: mov %eax,-0x4(%rbp)
0x00000000004004db <+39>: addq $0x4,-0x18(%rbp)
0x00000000004004e0 <+44>: mov -0x18(%rbp),%rax
0x00000000004004e4 <+48>: mov (%rax),%eax
0x00000000004004e6 <+50>: test %eax,%eax
0x00000000004004e8 <+52>: jne 0x4004c7 <max+19>
0x00000000004004ea <+54>: mov -0x4(%rbp),%eax
0x00000000004004ed <+57>: pop %rbp
0x00000000004004ee <+58>: retq
End of assembler dump.
(gdb) ni
0x00000000004004bc in max ()
(gdb) print $rbp
$1 = (void *) 0x7fffffffdf10
(gdb) print $rsp
$2 = (void *) 0x7fffffffdf10
The -0x18(%rbp) location is definitely inside the red zone. I'm not sure how the compiler uses that but it can probably do whatever the hack it wants in there. Your local int seems to be stored at -0x4(%rbp) later on, so I guess -0x18(%rbp) is just some sort of temporary buffer.
You could also ask the compiler to output its emitted assembler code. Notice that there is no observable side-effect in your program, so the compiler could optimize it to a nop -or compute the max at compile-time, etc.
However,compiling your code with (GCC 4.9.1 Debian/x86-64)
gcc -fverbose-asm -O -S main.c
I'm getting a file main.s containing (with several lines before and after) :
.globl max
.type max, #function
max:
.LFB0:
.file 1 "main.c"
.loc 1 4 0
.cfi_startproc
.LVL0:
.loc 1 5 0
movl (%rdi), %eax # *pt_5(D), val
.LVL1:
.loc 1 6 0
testl %eax, %eax # val
je .L2 #,
movl %eax, %edx # val, val
.L3:
cmpl %edx, %eax # val, val
cmovl %edx, %eax # val,, val, val
.LVL2:
.loc 1 12 0
addq $4, %rdi #, pt
.LVL3:
.loc 1 6 0
movl (%rdi), %edx # MEM[base: pt_8, offset: 0B], val
testl %edx, %edx # val
jne .L3 #,
.L2:
.loc 1 15 0
rep ret
.cfi_endproc
.LFE0:
.size max, .-max
.globl main
.type main, #function
main:
.LFB1:
.loc 1 18 0
.cfi_startproc
.loc 1 20 0
movl $data_items, %edi #,
call max #
.LVL4:
.loc 1 23 0
movl $0, %eax #,
ret
.cfi_endproc
.LFE1:
.size main, .-main
.globl data_items
.data
.align 32
.type data_items, #object
.size data_items, 40
data_items:
.long 3
.long 67
.long 32
.long 4
.long 89
.long 6
.long 34
.long 2
.long 9
.long 0
.text
So you see that data_items goes into the data section (because of the .data directive)
BTW, GCC usually emits an assembler file transformed by the as assembler into an ELF file main.o containing the object code. That object file contains relocation directives and several sections which are later processed by the ld linker.
Related
I've been trying to develop a small OS and managed to switch into protected mode, in order to write C code instead of assembly, but since this means I can't use interrupt 10h anymore, I have to write chars to the video memory address. So I tried creating a new print function to easily print out whole strings instead of printing each char separately. That's where the problems came in, for some reason, while printing single chars with the printchar function works, this new print function doesn't work, no matter what I try.
Here's my C Code:
void print(char* message, int offset);
void printChar(char character, int offset);
void start() {
printChar('M', 2);
print("Test String", 4);
while (1) {
}
}
void print(char* msg, int offset) {
for (int i = 0; msg[i] != '\0'; i++)
{
printChar(msg[i], (i * 2) + offset);
}
}
void printChar(char character, int offset) {
unsigned char* vidmem = (unsigned char*)0xB8000;
*(vidmem + offset + 1) = character;
*(vidmem + offset + 2) = 0x0f;
}
I then use these commands to convert my code to binary and put it onto the second sector of a floppy disk with sectedit.
gcc -c test.c
objcopy -O binary -j .text test.o test.bin
Also here's the assembly code generated, when using objdump -d test.o
0000000000000000 <start>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 20 sub $0x20,%rsp
8: ba 02 00 00 00 mov $0x2,%edx
d: b9 4d 00 00 00 mov $0x4d,%ecx
12: e8 73 00 00 00 call 8a <printChar>
17: ba 04 00 00 00 mov $0x4,%edx
1c: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 23 <start+0x23>
23: 48 89 c1 mov %rax,%rcx
26: e8 02 00 00 00 call 2d <print>
2b: eb fe jmp 2b <start+0x2b>
000000000000002d <print>:
2d: 55 push %rbp
2e: 48 89 e5 mov %rsp,%rbp
31: 48 83 ec 30 sub $0x30,%rsp
35: 48 89 4d 10 mov %rcx,0x10(%rbp)
39: 89 55 18 mov %edx,0x18(%rbp)
3c: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
43: eb 29 jmp 6e <print+0x41>
45: 8b 45 fc mov -0x4(%rbp),%eax
48: 8d 14 00 lea (%rax,%rax,1),%edx
4b: 8b 45 18 mov 0x18(%rbp),%eax
4e: 01 c2 add %eax,%edx
50: 8b 45 fc mov -0x4(%rbp),%eax
53: 48 63 c8 movslq %eax,%rcx
56: 48 8b 45 10 mov 0x10(%rbp),%rax
5a: 48 01 c8 add %rcx,%rax
5d: 0f b6 00 movzbl (%rax),%eax
60: 0f be c0 movsbl %al,%eax
63: 89 c1 mov %eax,%ecx
65: e8 20 00 00 00 call 8a <printChar>
6a: 83 45 fc 01 addl $0x1,-0x4(%rbp)
6e: 8b 45 fc mov -0x4(%rbp),%eax
71: 48 63 d0 movslq %eax,%rdx
74: 48 8b 45 10 mov 0x10(%rbp),%rax
78: 48 01 d0 add %rdx,%rax
7b: 0f b6 00 movzbl (%rax),%eax
7e: 84 c0 test %al,%al
80: 75 c3 jne 45 <print+0x18>
82: 90 nop
83: 90 nop
84: 48 83 c4 30 add $0x30,%rsp
88: 5d pop %rbp
89: c3 ret
000000000000008a <printChar>:
8a: 55 push %rbp
8b: 48 89 e5 mov %rsp,%rbp
8e: 48 83 ec 10 sub $0x10,%rsp
92: 89 c8 mov %ecx,%eax
94: 89 55 18 mov %edx,0x18(%rbp)
97: 88 45 10 mov %al,0x10(%rbp)
9a: 48 c7 45 f8 00 80 0b movq $0xb8000,-0x8(%rbp)
a1: 00
a2: 8b 45 18 mov 0x18(%rbp),%eax
a5: 48 98 cltq
a7: 48 8d 50 01 lea 0x1(%rax),%rdx
ab: 48 8b 45 f8 mov -0x8(%rbp),%rax
af: 48 01 c2 add %rax,%rdx
b2: 0f b6 45 10 movzbl 0x10(%rbp),%eax
b6: 88 02 mov %al,(%rdx)
b8: 8b 45 18 mov 0x18(%rbp),%eax
bb: 48 98 cltq
bd: 48 8d 50 02 lea 0x2(%rax),%rdx
c1: 48 8b 45 f8 mov -0x8(%rbp),%rax
c5: 48 01 d0 add %rdx,%rax
c8: c6 00 0f movb $0xf,(%rax)
cb: 90 nop
cc: 48 83 c4 10 add $0x10,%rsp
d0: 5d pop %rbp
d1: c3 ret
d2: 90 nop
d3: 90 nop
d4: 90 nop
d5: 90 nop
d6: 90 nop
d7: 90 nop
d8: 90 nop
d9: 90 nop
da: 90 nop
db: 90 nop
dc: 90 nop
dd: 90 nop
de: 90 nop
df: 90 nop
edit: The problem basically lied in me not doing this on a linux distribution, with all the things I'd need to do to do it in Windows not properly set up, huge thanks to MichaelPetch who explained the problems to me, I've now switched to a linux VM and after slightly correcting the code, it works (as the comments pointed out my offset was weird, I used that offset as it worked in the broken setup I had, but normally it shouldn't).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I observe some very weird performance for read and write access on Intel machine.
I wrote a C program that allocate an array first. The code of the program is at [1] ; You can compile it by running Make. (I don't use any compiling optimization.)
The sequence of the operations of the program is as follows:
allocate a char array;
init each element of array to be 1;
use clflush to flush the whole array from cache;
read each cache line of the array by using tmp = array[i];
(Do simple calculation after reading each cache line)
use clflush to flush the whole array from cache;
write each cache line of the array by using array[i] = tmp;
(Do the same simple calculation after reading each cache line)
I run the program on Intel(R) Xeon(R) CPU E5-1650 v2 # 3.50GHz (Haswell arch.) with turbo boost disabled.
The command I used to run the program is:
sudo ./rw-latency-test-compute 5210 10 1
I got the read latency for the whole array is 6670us, while the write latency for the whole array is 3518us.
The interesting part is
If I don't do any computation after I read/write a cache line, the read latency for the whole array is 2175us, while the write latency for the whole array is 3687us.
So doing computation seems speed up the execution... :-(
Do you have any suggestion/explanation on this weird performance?
The whole assembly code of the program can be found at [2].
The assembly code of the inner loop is as follows:
0000000000400898 <read_array>:
400898: 55 push %rbp
400899: 48 89 e5 mov %rsp,%rbp
40089c: 53 push %rbx
40089d: 48 83 ec 28 sub $0x28,%rsp
4008a1: 48 89 7d d8 mov %rdi,-0x28(%rbp)
4008a5: 48 89 75 d0 mov %rsi,-0x30(%rbp)
4008a9: c7 45 e8 00 00 00 00 movl $0x0,-0x18(%rbp)
4008b0: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp)
4008b7: eb 58 jmp 400911 <read_array+0x79>
4008b9: b8 00 00 00 00 mov $0x0,%eax
4008be: e8 38 ff ff ff callq 4007fb <sw_barrier>
4008c3: 8b 45 e4 mov -0x1c(%rbp),%eax
4008c6: 48 98 cltq
4008c8: 48 03 45 d8 add -0x28(%rbp),%rax
4008cc: 0f b6 00 movzbl (%rax),%eax
4008cf: 88 45 ef mov %al,-0x11(%rbp)
4008d2: 0f be 45 ef movsbl -0x11(%rbp),%eax
4008d6: 89 c1 mov %eax,%ecx
4008d8: 03 4d e8 add -0x18(%rbp),%ecx
4008db: ba 01 80 00 80 mov $0x80008001,%edx
4008e0: 89 c8 mov %ecx,%eax
4008e2: f7 ea imul %edx
4008e4: 8d 04 0a lea (%rdx,%rcx,1),%eax
4008e7: 89 c2 mov %eax,%edx
4008e9: c1 fa 0f sar $0xf,%edx
4008ec: 89 c8 mov %ecx,%eax
4008ee: c1 f8 1f sar $0x1f,%eax
4008f1: 89 d3 mov %edx,%ebx
4008f3: 29 c3 sub %eax,%ebx
4008f5: 89 d8 mov %ebx,%eax
4008f7: 89 45 e8 mov %eax,-0x18(%rbp)
4008fa: 8b 55 e8 mov -0x18(%rbp),%edx
4008fd: 89 d0 mov %edx,%eax
4008ff: c1 e0 10 shl $0x10,%eax
400902: 29 d0 sub %edx,%eax
400904: 89 ca mov %ecx,%edx
400906: 29 c2 sub %eax,%edx
400908: 89 d0 mov %edx,%eax
40090a: 89 45 e8 mov %eax,-0x18(%rbp)
40090d: 83 45 e4 40 addl $0x40,-0x1c(%rbp)
400911: 8b 45 e4 mov -0x1c(%rbp),%eax
400914: 48 98 cltq
400916: 48 3b 45 d0 cmp -0x30(%rbp),%rax
40091a: 7c 9d jl 4008b9 <read_array+0x21>
40091c: b8 e1 0f 40 00 mov $0x400fe1,%eax
400921: 8b 55 e8 mov -0x18(%rbp),%edx
400924: 89 d6 mov %edx,%esi
400926: 48 89 c7 mov %rax,%rdi
400929: b8 00 00 00 00 mov $0x0,%eax
40092e: e8 3d fd ff ff callq 400670 <printf#plt>
400933: 48 83 c4 28 add $0x28,%rsp
400937: 5b pop %rbx
400938: 5d pop %rbp
400939: c3 retq
000000000040093a <write_array>:
40093a: 55 push %rbp
40093b: 48 89 e5 mov %rsp,%rbp
40093e: 53 push %rbx
40093f: 48 83 ec 28 sub $0x28,%rsp
400943: 48 89 7d d8 mov %rdi,-0x28(%rbp)
400947: 48 89 75 d0 mov %rsi,-0x30(%rbp)
40094b: c6 45 ef 01 movb $0x1,-0x11(%rbp)
40094f: c7 45 e8 00 00 00 00 movl $0x0,-0x18(%rbp)
400956: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp)
40095d: eb 63 jmp 4009c2 <write_array+0x88>
40095f: b8 00 00 00 00 mov $0x0,%eax
400964: e8 92 fe ff ff callq 4007fb <sw_barrier>
400969: 8b 45 e4 mov -0x1c(%rbp),%eax
40096c: 48 98 cltq
40096e: 48 03 45 d8 add -0x28(%rbp),%rax
400972: 0f b6 55 ef movzbl -0x11(%rbp),%edx
400976: 88 10 mov %dl,(%rax)
400978: 8b 45 e4 mov -0x1c(%rbp),%eax
40097b: 48 98 cltq
40097d: 48 03 45 d8 add -0x28(%rbp),%rax
400981: 0f b6 00 movzbl (%rax),%eax
400984: 0f be c0 movsbl %al,%eax
400987: 89 c1 mov %eax,%ecx
400989: 03 4d e8 add -0x18(%rbp),%ecx
40098c: ba 01 80 00 80 mov $0x80008001,%edx
400991: 89 c8 mov %ecx,%eax
400993: f7 ea imul %edx
400995: 8d 04 0a lea (%rdx,%rcx,1),%eax
400998: 89 c2 mov %eax,%edx
40099a: c1 fa 0f sar $0xf,%edx
40099d: 89 c8 mov %ecx,%eax
40099f: c1 f8 1f sar $0x1f,%eax
4009a2: 89 d3 mov %edx,%ebx
4009a4: 29 c3 sub %eax,%ebx
4009a6: 89 d8 mov %ebx,%eax
4009a8: 89 45 e8 mov %eax,-0x18(%rbp)
4009ab: 8b 55 e8 mov -0x18(%rbp),%edx
4009ae: 89 d0 mov %edx,%eax
4009b0: c1 e0 10 shl $0x10,%eax
4009b3: 29 d0 sub %edx,%eax
4009b5: 89 ca mov %ecx,%edx
4009b7: 29 c2 sub %eax,%edx
4009b9: 89 d0 mov %edx,%eax
4009bb: 89 45 e8 mov %eax,-0x18(%rbp)
4009be: 83 45 e4 40 addl $0x40,-0x1c(%rbp)
4009c2: 8b 45 e4 mov -0x1c(%rbp),%eax
4009c5: 48 98 cltq
4009c7: 48 3b 45 d0 cmp -0x30(%rbp),%rax
4009cb: 7c 92 jl 40095f <write_array+0x25>
4009cd: b8 ee 0f 40 00 mov $0x400fee,%eax
4009d2: 8b 55 e8 mov -0x18(%rbp),%edx
4009d5: 89 d6 mov %edx,%esi
4009d7: 48 89 c7 mov %rax,%rdi
4009da: b8 00 00 00 00 mov $0x0,%eax
4009df: e8 8c fc ff ff callq 400670 <printf#plt>
4009e4: 48 83 c4 28 add $0x28,%rsp
4009e8: 5b pop %rbx
4009e9: 5d pop %rbp
4009ea: c3 retq
[1]https://github.com/PennPanda/rw-latency-test/blob/master/rw-latency-test-compute.c
[2] https://github.com/PennPanda/rw-latency-test/blob/2da88f1cccba40aba155317567199028b28bd250/rw-latency-test-compute.asm
Write is faster than read because if you read from RAM and use the value (that is, you don't just read and discard), the processor has to stall for the read at the point the value is used. However, write proceeds asynchronously and never stalls.
I am trying to convert an assembly program into null-free shellcode.
However, I am unsure how to go about this for certain instructions. Some of them way more complex than the examples I found in the web.
I used a C program from the web as an example, then converted to .s,using gcc -Wall -O -fverbose-asm -S example.c
gcc -c example.s -o example.o
gcc example.o -o example
objdump -d example
.file "test.c"
# GNU C (Debian 4.9.2-10) version 4.9.2 (x86_64-linux-gnu)
# compiled by GNU C version 4.9.2, GMP version 6.0.0, MPFR version 3.1.2-p3, MPC version 1.0.2
# GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
# options passed: -imultiarch x86_64-linux-gnu test.c -mtune=generic
# -march=x86-64 -O -Wall -fverbose-asm
# options enabled: -faggressive-loop-optimizations
# -fasynchronous-unwind-tables -fauto-inc-dec -fbranch-count-reg
# -fcombine-stack-adjustments -fcommon -fcompare-elim -fcprop-registers
# -fdefer-pop -fdelete-null-pointer-checks -fdwarf2-cfi-asm
# -fearly-inlining -feliminate-unused-debug-types -fforward-propagate
# -ffunction-cse -fgcse-lm -fgnu-runtime -fgnu-unique
# -fguess-branch-probability -fident -fif-conversion -fif-conversion2
# -finline -finline-atomics -finline-functions-called-once -fipa-profile
# -fipa-pure-const -fipa-reference -fira-hoist-pressure
# -fira-share-save-slots -fira-share-spill-slots -fivopts
# -fkeep-static-consts -fleading-underscore -fmath-errno -fmerge-constants
# -fmerge-debug-strings -fmove-loop-invariants -fomit-frame-pointer
# -fpeephole -fprefetch-loop-arrays -freg-struct-return
# -fsched-critical-path-heuristic -fsched-dep-count-heuristic
# -fsched-group-heuristic -fsched-interblock -fsched-last-insn-heuristic
# -fsched-rank-heuristic -fsched-spec -fsched-spec-insn-heuristic
# -fsched-stalled-insns-dep -fshow-column -fshrink-wrap -fsigned-zeros
# -fsplit-ivs-in-unroller -fsplit-wide-types -fstrict-volatile-bitfields
# -fsync-libcalls -ftoplevel-reorder -ftrapping-math -ftree-bit-ccp
# -ftree-ccp -ftree-ch -ftree-coalesce-vars -ftree-copy-prop
# -ftree-copyrename -ftree-cselim -ftree-dce -ftree-dominator-opts
# -ftree-dse -ftree-forwprop -ftree-fre -ftree-loop-if-convert
# -ftree-loop-im -ftree-loop-ivcanon -ftree-loop-optimize
# -ftree-parallelize-loops= -ftree-phiprop -ftree-pta -ftree-reassoc
# -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-sra -ftree-ter
# -funit-at-a-time -funwind-tables -fverbose-asm -fzero-initialized-in-bss
# -m128bit-long-double -m64 -m80387 -malign-stringops
# -mavx256-split-unaligned-load -mavx256-split-unaligned-store
# -mfancy-math-387 -mfp-ret-in-387 -mfxsr -mglibc -mieee-fp
# -mlong-double-80 -mmmx -mno-sse4 -mpush-args -mred-zone -msse -msse2
# -mtls-direct-seg-refs
.section .rodata.str1.1,"aMS",#progbits,1
.LC0:
.string "Could not create socket"
.LC1:
.string "127.0.0.1"
.LC2:
.string "connect error"
.LC3:
.string "Connected\n"
.section .rodata.str1.8,"aMS",#progbits,1
.align 8
.LC4:
.string "Hola Redon , I really appreaciate your help\n\r\n"
.section .rodata.str1.1
.LC5:
.string "Send failed"
.LC6:
.string "Data Send\n"
.LC7:
.string "recv failed"
.LC8:
.string "Reply received\n"
.text
.globl main
.type main, #function
main:
.LFB29:
.cfi_startproc
pushq %rbx #
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
subq $2016, %rsp #,
.cfi_def_cfa_offset 2032
movl $0, %edx #,
movl $1, %esi #,
movl $2, %edi #,
call socket #
movl %eax, %ebx #, socket_desc
cmpl $-1, %eax #, socket_desc
jne .L2 #,
movl $.LC0, %edi #,
movl $0, %eax #,
call printf #
.L2:
movl $.LC1, %edi #,
call inet_addr #
movl %eax, 2004(%rsp) # D.3169, server.sin_addr.s_addr
movw $2, 2000(%rsp) #, server.sin_family
movw $14093, 2002(%rsp) #, server.sin_port
movl $16, %edx #,
leaq 2000(%rsp), %rsi #, tmp96
movl %ebx, %edi # socket_desc,
call connect #
testl %eax, %eax # D.3168
jns .L3 #,
movl $.LC2, %edi #,
call puts #
movl $1, %eax #, D.3168
jmp .L4 #
.L3:
movl $.LC3, %edi #,
call puts #
movl $0, %ecx #,
movl $46, %edx #,
movl $.LC4, %esi #,
movl %ebx, %edi # socket_desc,
call send #
testq %rax, %rax # D.3170
jns .L5 #,
movl $.LC5, %edi #,
call puts #
movl $1, %eax #, D.3168
jmp .L4 #
.L5:
movl $.LC6, %edi #,
call puts #
movl $0, %ecx #,
movl $2000, %edx #,
movq %rsp, %rsi #,
movl %ebx, %edi # socket_desc,
call recv #
testq %rax, %rax # D.3170
jns .L6 #,
movl $.LC7, %edi #,
call puts #
.L6:
movl $.LC8, %edi #,
call puts #
movq %rsp, %rdi #,
call puts #
movl $0, %eax #, D.3168
.L4:
addq $2016, %rsp #,
.cfi_def_cfa_offset 16
popq %rbx #
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE29:
.size main, .-main
.ident "GCC: (Debian 4.9.2-10) 4.9.2"
.section .note.GNU-stack,"",#progbits
Wich give this:
test: file format elf64-x86-64
Disassembly of section .init:
0000000000400500 <_init>:
400500: 48 83 ec 08 sub $0x8,%rsp
400504: 48 8b 05 fd 06 20 00 mov 0x2006fd(%rip),%rax # 600c08 <_DYNAMIC+0x1d0>
40050b: 48 85 c0 test %rax,%rax
40050e: 74 05 je 400515 <_init+0x15>
400510: e8 7b 00 00 00 callq 400590 <__gmon_start__#plt>
400515: 48 83 c4 08 add $0x8,%rsp
400519: c3 retq
Disassembly of section .plt:
0000000000400520 <recv#plt-0x10>:
400520: ff 35 f2 06 20 00 pushq 0x2006f2(%rip) # 600c18 <_GLOBAL_OFFSET_TABLE_+0x8>
400526: ff 25 f4 06 20 00 jmpq *0x2006f4(%rip) # 600c20 <_GLOBAL_OFFSET_TABLE_+0x10>
40052c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400530 <recv#plt>:
400530: ff 25 f2 06 20 00 jmpq *0x2006f2(%rip) # 600c28 <_GLOBAL_OFFSET_TABLE_+0x18>
400536: 68 00 00 00 00 pushq $0x0
40053b: e9 e0 ff ff ff jmpq 400520 <_init+0x20>
0000000000400540 <puts#plt>:
400540: ff 25 ea 06 20 00 jmpq *0x2006ea(%rip) # 600c30 <_GLOBAL_OFFSET_TABLE_+0x20>
400546: 68 01 00 00 00 pushq $0x1
40054b: e9 d0 ff ff ff jmpq 400520 <_init+0x20>
0000000000400550 <send#plt>:
400550: ff 25 e2 06 20 00 jmpq *0x2006e2(%rip) # 600c38 <_GLOBAL_OFFSET_TABLE_+0x28>
400556: 68 02 00 00 00 pushq $0x2
40055b: e9 c0 ff ff ff jmpq 400520 <_init+0x20>
0000000000400560 <printf#plt>:
400560: ff 25 da 06 20 00 jmpq *0x2006da(%rip) # 600c40 <_GLOBAL_OFFSET_TABLE_+0x30>
400566: 68 03 00 00 00 pushq $0x3
40056b: e9 b0 ff ff ff jmpq 400520 <_init+0x20>
0000000000400570 <__libc_start_main#plt>:
400570: ff 25 d2 06 20 00 jmpq *0x2006d2(%rip) # 600c48 <_GLOBAL_OFFSET_TABLE_+0x38>
400576: 68 04 00 00 00 pushq $0x4
40057b: e9 a0 ff ff ff jmpq 400520 <_init+0x20>
0000000000400580 <inet_addr#plt>:
400580: ff 25 ca 06 20 00 jmpq *0x2006ca(%rip) # 600c50 <_GLOBAL_OFFSET_TABLE_+0x40>
400586: 68 05 00 00 00 pushq $0x5
40058b: e9 90 ff ff ff jmpq 400520 <_init+0x20>
0000000000400590 <__gmon_start__#plt>:
400590: ff 25 c2 06 20 00 jmpq *0x2006c2(%rip) # 600c58 <_GLOBAL_OFFSET_TABLE_+0x48>
400596: 68 06 00 00 00 pushq $0x6
40059b: e9 80 ff ff ff jmpq 400520 <_init+0x20>
00000000004005a0 <connect#plt>:
4005a0: ff 25 ba 06 20 00 jmpq *0x2006ba(%rip) # 600c60 <_GLOBAL_OFFSET_TABLE_+0x50>
4005a6: 68 07 00 00 00 pushq $0x7
4005ab: e9 70 ff ff ff jmpq 400520 <_init+0x20>
00000000004005b0 <socket#plt>:
4005b0: ff 25 b2 06 20 00 jmpq *0x2006b2(%rip) # 600c68 <_GLOBAL_OFFSET_TABLE_+0x58>
4005b6: 68 08 00 00 00 pushq $0x8
4005bb: e9 60 ff ff ff jmpq 400520 <_init+0x20>
Disassembly of section .text:
00000000004005c0 <_start>:
4005c0: 31 ed xor %ebp,%ebp
4005c2: 49 89 d1 mov %rdx,%r9
4005c5: 5e pop %rsi
4005c6: 48 89 e2 mov %rsp,%rdx
4005c9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
4005cd: 50 push %rax
4005ce: 54 push %rsp
4005cf: 49 c7 c0 30 08 40 00 mov $0x400830,%r8
4005d6: 48 c7 c1 c0 07 40 00 mov $0x4007c0,%rcx
4005dd: 48 c7 c7 b6 06 40 00 mov $0x4006b6,%rdi
4005e4: e8 87 ff ff ff callq 400570 <__libc_start_main#plt>
4005e9: f4 hlt
4005ea: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
00000000004005f0 <deregister_tm_clones>:
4005f0: b8 87 0c 60 00 mov $0x600c87,%eax
4005f5: 55 push %rbp
4005f6: 48 2d 80 0c 60 00 sub $0x600c80,%rax
4005fc: 48 83 f8 0e cmp $0xe,%rax
400600: 48 89 e5 mov %rsp,%rbp
400603: 76 1b jbe 400620 <deregister_tm_clones+0x30>
400605: b8 00 00 00 00 mov $0x0,%eax
40060a: 48 85 c0 test %rax,%rax
40060d: 74 11 je 400620 <deregister_tm_clones+0x30>
40060f: 5d pop %rbp
400610: bf 80 0c 60 00 mov $0x600c80,%edi
400615: ff e0 jmpq *%rax
400617: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
40061e: 00 00
400620: 5d pop %rbp
400621: c3 retq
400622: 66 66 66 66 66 2e 0f data16 data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
400629: 1f 84 00 00 00 00 00
0000000000400630 <register_tm_clones>:
400630: be 80 0c 60 00 mov $0x600c80,%esi
400635: 55 push %rbp
400636: 48 81 ee 80 0c 60 00 sub $0x600c80,%rsi
40063d: 48 c1 fe 03 sar $0x3,%rsi
400641: 48 89 e5 mov %rsp,%rbp
400644: 48 89 f0 mov %rsi,%rax
400647: 48 c1 e8 3f shr $0x3f,%rax
40064b: 48 01 c6 add %rax,%rsi
40064e: 48 d1 fe sar %rsi
400651: 74 15 je 400668 <register_tm_clones+0x38>
400653: b8 00 00 00 00 mov $0x0,%eax
400658: 48 85 c0 test %rax,%rax
40065b: 74 0b je 400668 <register_tm_clones+0x38>
40065d: 5d pop %rbp
40065e: bf 80 0c 60 00 mov $0x600c80,%edi
400663: ff e0 jmpq *%rax
400665: 0f 1f 00 nopl (%rax)
400668: 5d pop %rbp
400669: c3 retq
40066a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400670 <__do_global_dtors_aux>:
400670: 80 3d 09 06 20 00 00 cmpb $0x0,0x200609(%rip) # 600c80 <__TMC_END__>
400677: 75 11 jne 40068a <__do_global_dtors_aux+0x1a>
400679: 55 push %rbp
40067a: 48 89 e5 mov %rsp,%rbp
40067d: e8 6e ff ff ff callq 4005f0 <deregister_tm_clones>
400682: 5d pop %rbp
400683: c6 05 f6 05 20 00 01 movb $0x1,0x2005f6(%rip) # 600c80 <__TMC_END__>
40068a: f3 c3 repz retq
40068c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400690 <frame_dummy>:
400690: bf 30 0a 60 00 mov $0x600a30,%edi
400695: 48 83 3f 00 cmpq $0x0,(%rdi)
400699: 75 05 jne 4006a0 <frame_dummy+0x10>
40069b: eb 93 jmp 400630 <register_tm_clones>
40069d: 0f 1f 00 nopl (%rax)
4006a0: b8 00 00 00 00 mov $0x0,%eax
4006a5: 48 85 c0 test %rax,%rax
4006a8: 74 f1 je 40069b <frame_dummy+0xb>
4006aa: 55 push %rbp
4006ab: 48 89 e5 mov %rsp,%rbp
4006ae: ff d0 callq *%rax
4006b0: 5d pop %rbp
4006b1: e9 7a ff ff ff jmpq 400630 <register_tm_clones>
00000000004006b6 <main>:
4006b6: 53 push %rbx
4006b7: 48 81 ec e0 07 00 00 sub $0x7e0,%rsp
4006be: ba 00 00 00 00 mov $0x0,%edx
4006c3: be 01 00 00 00 mov $0x1,%esi
4006c8: bf 02 00 00 00 mov $0x2,%edi
4006cd: e8 de fe ff ff callq 4005b0 <socket#plt>
4006d2: 89 c3 mov %eax,%ebx
4006d4: 83 f8 ff cmp $0xffffffff,%eax
4006d7: 75 0f jne 4006e8 <main+0x32>
4006d9: bf 44 08 40 00 mov $0x400844,%edi
4006de: b8 00 00 00 00 mov $0x0,%eax
4006e3: e8 78 fe ff ff callq 400560 <printf#plt>
4006e8: bf 5c 08 40 00 mov $0x40085c,%edi
4006ed: e8 8e fe ff ff callq 400580 <inet_addr#plt>
4006f2: 89 84 24 d4 07 00 00 mov %eax,0x7d4(%rsp)
4006f9: 66 c7 84 24 d0 07 00 movw $0x2,0x7d0(%rsp)
400700: 00 02 00
400703: 66 c7 84 24 d2 07 00 movw $0x370d,0x7d2(%rsp)
40070a: 00 0d 37
40070d: ba 10 00 00 00 mov $0x10,%edx
400712: 48 8d b4 24 d0 07 00 lea 0x7d0(%rsp),%rsi
400719: 00
40071a: 89 df mov %ebx,%edi
40071c: e8 7f fe ff ff callq 4005a0 <connect#plt>
400721: 85 c0 test %eax,%eax
400723: 79 11 jns 400736 <main+0x80>
400725: bf 66 08 40 00 mov $0x400866,%edi
40072a: e8 11 fe ff ff callq 400540 <puts#plt>
40072f: b8 01 00 00 00 mov $0x1,%eax
400734: eb 7a jmp 4007b0 <main+0xfa>
400736: bf 74 08 40 00 mov $0x400874,%edi
40073b: e8 00 fe ff ff callq 400540 <puts#plt>
400740: b9 00 00 00 00 mov $0x0,%ecx
400745: ba 2e 00 00 00 mov $0x2e,%edx
40074a: be b8 08 40 00 mov $0x4008b8,%esi
40074f: 89 df mov %ebx,%edi
400751: e8 fa fd ff ff callq 400550 <send#plt>
400756: 48 85 c0 test %rax,%rax
400759: 79 11 jns 40076c <main+0xb6>
40075b: bf 7f 08 40 00 mov $0x40087f,%edi
400760: e8 db fd ff ff callq 400540 <puts#plt>
400765: b8 01 00 00 00 mov $0x1,%eax
40076a: eb 44 jmp 4007b0 <main+0xfa>
40076c: bf 8b 08 40 00 mov $0x40088b,%edi
400771: e8 ca fd ff ff callq 400540 <puts#plt>
400776: b9 00 00 00 00 mov $0x0,%ecx
40077b: ba d0 07 00 00 mov $0x7d0,%edx
400780: 48 89 e6 mov %rsp,%rsi
400783: 89 df mov %ebx,%edi
400785: e8 a6 fd ff ff callq 400530 <recv#plt>
40078a: 48 85 c0 test %rax,%rax
40078d: 79 0a jns 400799 <main+0xe3>
40078f: bf 96 08 40 00 mov $0x400896,%edi
400794: e8 a7 fd ff ff callq 400540 <puts#plt>
400799: bf a2 08 40 00 mov $0x4008a2,%edi
40079e: e8 9d fd ff ff callq 400540 <puts#plt>
4007a3: 48 89 e7 mov %rsp,%rdi
4007a6: e8 95 fd ff ff callq 400540 <puts#plt>
4007ab: b8 00 00 00 00 mov $0x0,%eax
4007b0: 48 81 c4 e0 07 00 00 add $0x7e0,%rsp
4007b7: 5b pop %rbx
4007b8: c3 retq
4007b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000004007c0 <__libc_csu_init>:
4007c0: 41 57 push %r15
4007c2: 41 89 ff mov %edi,%r15d
4007c5: 41 56 push %r14
4007c7: 49 89 f6 mov %rsi,%r14
4007ca: 41 55 push %r13
4007cc: 49 89 d5 mov %rdx,%r13
4007cf: 41 54 push %r12
4007d1: 4c 8d 25 48 02 20 00 lea 0x200248(%rip),%r12 # 600a20 <__frame_dummy_init_array_entry>
4007d8: 55 push %rbp
4007d9: 48 8d 2d 48 02 20 00 lea 0x200248(%rip),%rbp # 600a28 <__init_array_end>
4007e0: 53 push %rbx
4007e1: 4c 29 e5 sub %r12,%rbp
4007e4: 31 db xor %ebx,%ebx
4007e6: 48 c1 fd 03 sar $0x3,%rbp
4007ea: 48 83 ec 08 sub $0x8,%rsp
4007ee: e8 0d fd ff ff callq 400500 <_init>
4007f3: 48 85 ed test %rbp,%rbp
4007f6: 74 1e je 400816 <__libc_csu_init+0x56>
4007f8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
4007ff: 00
400800: 4c 89 ea mov %r13,%rdx
400803: 4c 89 f6 mov %r14,%rsi
400806: 44 89 ff mov %r15d,%edi
400809: 41 ff 14 dc callq *(%r12,%rbx,8)
40080d: 48 83 c3 01 add $0x1,%rbx
400811: 48 39 eb cmp %rbp,%rbx
400814: 75 ea jne 400800 <__libc_csu_init+0x40>
400816: 48 83 c4 08 add $0x8,%rsp
40081a: 5b pop %rbx
40081b: 5d pop %rbp
40081c: 41 5c pop %r12
40081e: 41 5d pop %r13
400820: 41 5e pop %r14
400822: 41 5f pop %r15
400824: c3 retq
400825: 66 66 2e 0f 1f 84 00 data16 nopw %cs:0x0(%rax,%rax,1)
40082c: 00 00 00 00
0000000000400830 <__libc_csu_fini>:
400830: f3 c3 repz retq
Disassembly of section .fini:
0000000000400834 <_fini>:
400834: 48 83 ec 08 sub $0x8,%rsp
400838: 48 83 c4 08 add $0x8,%rsp
40083c: c3 retq
As you can see it´s a lot .... First question would be... null bytes from my .init and .plt seccion will affect my shellcode or just only the ones in my .text Section?.
I know for example in a case where I have :
ba 00 00 00 00 mov $0x0,%edx I can apply xor %edx,edx
b8 01 00 00 00 mov $0x1,%eax, can apply xor %eax,eax aswell?
but what about the cases like :
ff 35 f2 06 20 00 pushq 0x2006f2(%rip) or
66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
Since Im a newbie who wants to learn any help would be appreciate, Yes I have read Smashing The Stack For Fun And Profit but english is not my mother language and like I said Im a newbie so not everything is clear for me.
Thanks in advanced.
The following is my C file:
int main()
{
return 36;
}
It contains only return statement. But if I use the size command, it shows the
output like this:
mohanraj#ltsp63:~/Development/chap8$ size a.out
text data bss dec hex filename
1056 252 8 1316 524 a.out
mohanraj#ltsp63:~/Development/chap8$
Even though my program does not contain any global variable, or undeclared data. But, the output shows data segment have 252 and the bss have 8 bytes. So, why the output is like this? what is 252 and 8 refers.
Size Command
First see the definition of each column:
text - Actual machine instructions that your CPU going to execute. Linux allows to share this data.
data - All initialized variables (declarations) declared in a program (e.g., float salary=123.45;).
bss - The BSS consists of uninitialized data such as arrays that you have not set any values to or null pointers.
As Blue Moon said. On Linux, the execution starts by calling _start() function. Which does environment setup. Every C program has hidden "libraries" that depends on compilator you using. There are settings for global parameters, exit calls and after complete configuration it finally calls your main() function.
ASFAIK there's no way to see how your code looks encapsulated with configuration and _start() function. But I can show you that even your code contains more information than you thought the closer to hardware we are.
Hint:
Type readelf -a a.out to see how much information your exec really carrying.
What is inside?
Do not compare code in your source file to the size of executable file, it depends on the OS, compilator, and used libraries.
In my example, with exactly the same code, SIZE returns:
eryk#eryk-pc:~$ gcc a.c
eryk#eryk-pc:~$ size a.out
text data bss dec hex filename
1033 276 4 1313 521 a.out
Let's see what is inside...
eryk#eryk-pc:~$ gcc -S a.c
This will run the preprocessor over a.c, perform the initial compilation and then stop before the assembler is run.
eryk#eryk-pc:~$ cat a.s
.file "a.c"
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl $36, %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",#progbits
Then look on the assembly code
eryk#eryk-pc:~$ objdump -d -M intel -S a.out
a.out: file format elf32-i386
Disassembly of section .init:
08048294 <_init>:
8048294: 53 push ebx
8048295: 83 ec 08 sub esp,0x8
8048298: e8 83 00 00 00 call 8048320 <__x86.get_pc_thunk.bx>
804829d: 81 c3 63 1d 00 00 add ebx,0x1d63
80482a3: 8b 83 fc ff ff ff mov eax,DWORD PTR [ebx-0x4]
80482a9: 85 c0 test eax,eax
80482ab: 74 05 je 80482b2 <_init+0x1e>
80482ad: e8 1e 00 00 00 call 80482d0 <__gmon_start__#plt>
80482b2: 83 c4 08 add esp,0x8
80482b5: 5b pop ebx
80482b6: c3 ret
Disassembly of section .plt:
080482c0 <__gmon_start__#plt-0x10>:
80482c0: ff 35 04 a0 04 08 push DWORD PTR ds:0x804a004
80482c6: ff 25 08 a0 04 08 jmp DWORD PTR ds:0x804a008
80482cc: 00 00 add BYTE PTR [eax],al
...
080482d0 <__gmon_start__#plt>:
80482d0: ff 25 0c a0 04 08 jmp DWORD PTR ds:0x804a00c
80482d6: 68 00 00 00 00 push 0x0
80482db: e9 e0 ff ff ff jmp 80482c0 <_init+0x2c>
080482e0 <__libc_start_main#plt>:
80482e0: ff 25 10 a0 04 08 jmp DWORD PTR ds:0x804a010
80482e6: 68 08 00 00 00 push 0x8
80482eb: e9 d0 ff ff ff jmp 80482c0 <_init+0x2c>
Disassembly of section .text:
080482f0 <_start>:
80482f0: 31 ed xor ebp,ebp
80482f2: 5e pop esi
80482f3: 89 e1 mov ecx,esp
80482f5: 83 e4 f0 and esp,0xfffffff0
80482f8: 50 push eax
80482f9: 54 push esp
80482fa: 52 push edx
80482fb: 68 70 84 04 08 push 0x8048470
8048300: 68 00 84 04 08 push 0x8048400
8048305: 51 push ecx
8048306: 56 push esi
8048307: 68 ed 83 04 08 push 0x80483ed
804830c: e8 cf ff ff ff call 80482e0 <__libc_start_main#plt>
8048311: f4 hlt
8048312: 66 90 xchg ax,ax
8048314: 66 90 xchg ax,ax
8048316: 66 90 xchg ax,ax
8048318: 66 90 xchg ax,ax
804831a: 66 90 xchg ax,ax
804831c: 66 90 xchg ax,ax
804831e: 66 90 xchg ax,ax
08048320 <__x86.get_pc_thunk.bx>:
8048320: 8b 1c 24 mov ebx,DWORD PTR [esp]
8048323: c3 ret
8048324: 66 90 xchg ax,ax
8048326: 66 90 xchg ax,ax
8048328: 66 90 xchg ax,ax
804832a: 66 90 xchg ax,ax
804832c: 66 90 xchg ax,ax
804832e: 66 90 xchg ax,ax
08048330 <deregister_tm_clones>:
8048330: b8 1f a0 04 08 mov eax,0x804a01f
8048335: 2d 1c a0 04 08 sub eax,0x804a01c
804833a: 83 f8 06 cmp eax,0x6
804833d: 77 01 ja 8048340 <deregister_tm_clones+0x10>
804833f: c3 ret
8048340: b8 00 00 00 00 mov eax,0x0
8048345: 85 c0 test eax,eax
8048347: 74 f6 je 804833f <deregister_tm_clones+0xf>
8048349: 55 push ebp
804834a: 89 e5 mov ebp,esp
804834c: 83 ec 18 sub esp,0x18
804834f: c7 04 24 1c a0 04 08 mov DWORD PTR [esp],0x804a01c
8048356: ff d0 call eax
8048358: c9 leave
8048359: c3 ret
804835a: 8d b6 00 00 00 00 lea esi,[esi+0x0]
08048360 <register_tm_clones>:
8048360: b8 1c a0 04 08 mov eax,0x804a01c
8048365: 2d 1c a0 04 08 sub eax,0x804a01c
804836a: c1 f8 02 sar eax,0x2
804836d: 89 c2 mov edx,eax
804836f: c1 ea 1f shr edx,0x1f
8048372: 01 d0 add eax,edx
8048374: d1 f8 sar eax,1
8048376: 75 01 jne 8048379 <register_tm_clones+0x19>
8048378: c3 ret
8048379: ba 00 00 00 00 mov edx,0x0
804837e: 85 d2 test edx,edx
8048380: 74 f6 je 8048378 <register_tm_clones+0x18>
8048382: 55 push ebp
8048383: 89 e5 mov ebp,esp
8048385: 83 ec 18 sub esp,0x18
8048388: 89 44 24 04 mov DWORD PTR [esp+0x4],eax
804838c: c7 04 24 1c a0 04 08 mov DWORD PTR [esp],0x804a01c
8048393: ff d2 call edx
8048395: c9 leave
8048396: c3 ret
8048397: 89 f6 mov esi,esi
8048399: 8d bc 27 00 00 00 00 lea edi,[edi+eiz*1+0x0]
080483a0 <__do_global_dtors_aux>:
80483a0: 80 3d 1c a0 04 08 00 cmp BYTE PTR ds:0x804a01c,0x0
80483a7: 75 13 jne 80483bc <__do_global_dtors_aux+0x1c>
80483a9: 55 push ebp
80483aa: 89 e5 mov ebp,esp
80483ac: 83 ec 08 sub esp,0x8
80483af: e8 7c ff ff ff call 8048330 <deregister_tm_clones>
80483b4: c6 05 1c a0 04 08 01 mov BYTE PTR ds:0x804a01c,0x1
80483bb: c9 leave
80483bc: f3 c3 repz ret
80483be: 66 90 xchg ax,ax
080483c0 <frame_dummy>:
80483c0: a1 10 9f 04 08 mov eax,ds:0x8049f10
80483c5: 85 c0 test eax,eax
80483c7: 74 1f je 80483e8 <frame_dummy+0x28>
80483c9: b8 00 00 00 00 mov eax,0x0
80483ce: 85 c0 test eax,eax
80483d0: 74 16 je 80483e8 <frame_dummy+0x28>
80483d2: 55 push ebp
80483d3: 89 e5 mov ebp,esp
80483d5: 83 ec 18 sub esp,0x18
80483d8: c7 04 24 10 9f 04 08 mov DWORD PTR [esp],0x8049f10
80483df: ff d0 call eax
80483e1: c9 leave
80483e2: e9 79 ff ff ff jmp 8048360 <register_tm_clones>
80483e7: 90 nop
80483e8: e9 73 ff ff ff jmp 8048360 <register_tm_clones>
080483ed <main>:
80483ed: 55 push ebp
80483ee: 89 e5 mov ebp,esp
80483f0: b8 24 00 00 00 mov eax,0x24
80483f5: 5d pop ebp
80483f6: c3 ret
80483f7: 66 90 xchg ax,ax
80483f9: 66 90 xchg ax,ax
80483fb: 66 90 xchg ax,ax
80483fd: 66 90 xchg ax,ax
80483ff: 90 nop
08048400 <__libc_csu_init>:
8048400: 55 push ebp
8048401: 57 push edi
8048402: 31 ff xor edi,edi
8048404: 56 push esi
8048405: 53 push ebx
8048406: e8 15 ff ff ff call 8048320 <__x86.get_pc_thunk.bx>
804840b: 81 c3 f5 1b 00 00 add ebx,0x1bf5
8048411: 83 ec 1c sub esp,0x1c
8048414: 8b 6c 24 30 mov ebp,DWORD PTR [esp+0x30]
8048418: 8d b3 0c ff ff ff lea esi,[ebx-0xf4]
804841e: e8 71 fe ff ff call 8048294 <_init>
8048423: 8d 83 08 ff ff ff lea eax,[ebx-0xf8]
8048429: 29 c6 sub esi,eax
804842b: c1 fe 02 sar esi,0x2
804842e: 85 f6 test esi,esi
8048430: 74 27 je 8048459 <__libc_csu_init+0x59>
8048432: 8d b6 00 00 00 00 lea esi,[esi+0x0]
8048438: 8b 44 24 38 mov eax,DWORD PTR [esp+0x38]
804843c: 89 2c 24 mov DWORD PTR [esp],ebp
804843f: 89 44 24 08 mov DWORD PTR [esp+0x8],eax
8048443: 8b 44 24 34 mov eax,DWORD PTR [esp+0x34]
8048447: 89 44 24 04 mov DWORD PTR [esp+0x4],eax
804844b: ff 94 bb 08 ff ff ff call DWORD PTR [ebx+edi*4-0xf8]
8048452: 83 c7 01 add edi,0x1
8048455: 39 f7 cmp edi,esi
8048457: 75 df jne 8048438 <__libc_csu_init+0x38>
8048459: 83 c4 1c add esp,0x1c
804845c: 5b pop ebx
804845d: 5e pop esi
804845e: 5f pop edi
804845f: 5d pop ebp
8048460: c3 ret
8048461: eb 0d jmp 8048470 <__libc_csu_fini>
8048463: 90 nop
8048464: 90 nop
8048465: 90 nop
8048466: 90 nop
8048467: 90 nop
8048468: 90 nop
8048469: 90 nop
804846a: 90 nop
804846b: 90 nop
804846c: 90 nop
804846d: 90 nop
804846e: 90 nop
804846f: 90 nop
08048470 <__libc_csu_fini>:
8048470: f3 c3 repz ret
Disassembly of section .fini:
08048474 <_fini>:
8048474: 53 push ebx
8048475: 83 ec 08 sub esp,0x8
8048478: e8 a3 fe ff ff call 8048320 <__x86.get_pc_thunk.bx>
804847d: 81 c3 83 1b 00 00 add ebx,0x1b83
8048483: 83 c4 08 add esp,0x8
8048486: 5b pop ebx
8048487: c3 ret
Next step would converting above code to 01 notation.
As you can see. Even simple c program contains complicated operation the closer to hardware your code is. I hope I have explained to you why the executable file is bigger than you thought. If you have any doubts, feel free to comment my post. I will edit my answer immediately.
I have the following from an objdump. This was C code compiled by gcc for an IA32.
08048e9a <my_func>:
8048e9a: 55 push %ebp
8048e9b: 89 e5 mov %esp,%ebp
8048e9d: 83 ec 48 sub $0x48,%esp
8048ea0: 89 5d f4 mov %ebx,-0xc(%ebp)
8048ea3: 89 75 f8 mov %esi,-0x8(%ebp)
8048ea6: 89 7d fc mov %edi,-0x4(%ebp)
8048ea9: 8d 5d d0 lea -0x30(%ebp),%ebx
8048eac: 89 5c 24 04 mov %ebx,0x4(%esp)
8048eb0: 8b 45 08 mov 0x8(%ebp),%eax
8048eb3: 89 04 24 mov %eax,(%esp)
8048eb6: e8 52 04 00 00 call 804930d <read_num>
8048ebb: 8d 7d dc lea -0x24(%ebp),%edi
8048ebe: be 00 00 00 00 mov $0x0,%esi
8048ec3: 8b 03 mov (%ebx),%eax
8048ec5: 3b 43 0c cmp 0xc(%ebx),%eax
8048ec8: 74 05 je 8048ecf <my_func+0x35>
8048eca: e8 fc 03 00 00 call 80492cb <other_func>
8048ecf: 03 33 add (%ebx),%esi
I am interested in finding out the values being compared on line 8048ec5 In gdb I can step to this line and I can read %eax just fine from info registers but how can I read 0xc(%ebx)? This means 0xc offset from %ebx or 0xc + %ebx?
It refers to the 32-bit value at the address %ebx + 0xc in memory.