Assembly

Hi, Isn't C supposed to translate quite closely to machine instructions? What is this?

Other urls found in this thread:

en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI
twitter.com/SFWRedditImages

looks readable enough to me

26 lines of C translated into 23 lines of assembly.

Can't you do the loop in 2-3 instructions?

are you using gcc to compile arm? I hear it's pretty bad at that

enable optimization flags

C is a high level language

You want to increment a variables stored in the stack, but you can only do arithmetic operation on the registers, hence the mov instructions. This code is definitely optimizable. Is it compiled with -O3?

Go fuck yourself.

Are you retarded? You never saw assembly code? How fuck you are supposed to loop+count loop+ update memory in 2 instructions?

It can be done in 4 instructions (cmpq, je, addq, jmp), but this appears to have not been compiled with optimizations. Hence, i64 is located at -0x18(%rbp), and must be moved to and from there every time it is referenced. If optimizations were used, it would be kept entirely in a register.

The variables do not have to be stored on the stack at all. This is clearly unoptimized, as otherwise, the stack would not be touched much at all.

By close to machine code I think they just mean the language has pointers and goto desu

My mistake, thought that the compiler would know to generate opcodes which operate on register values rather than values in the stack.

Set that shit to Intel yo

bp - base pointer (middle of stack); local variables appear below bp, parameters appear above bp
sp - current top of stack

- Store the base pointer of the calling function
pushq %rbp

- Update the base pointer to the stack pointer (e.g. parameters to the function are now above bp)
movq %rsp, %rbp

- Subtract 0x20 from the stack pointer to allow for local variables
subq $0x20, %rsp

The mov rbp -> rax, add 1 rax, mov rax -> rbp
is a bit unnecessary if you were to write the assembly yourself since you know you don't need the other register.

I guess the simple assembly loop would look like this:
movq 1 %r_i64
loop: cmpq 0 %r_i64
je done
addq 1, %r_i64
jmp loop
done: retq

Incidentally, when GCC is fed OP's code with -O2 optimizations or higher, the result is that the loop is completely removed. Behold how simple it looks:

.LC0:
.string "Hello World!"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
call puts
xor eax, eax
add rsp, 8
ret

it does, it is an optimization.
It is not turned on by default because you cannot store every variable in the registers and you have to implement it, go back and check how many you need then simplify it in order to get the "optimal".
They both do the same thing.

- Load the "effective" address (of a string) into register
leaq 0x6f(%rip), %rax

- COPY a long size (32 bits) value (0x0) into memory -0x4 (e.g. relative to bp)
movl $0x0, -0x4(%rbp)

- COPY a register into memory -0x8
movl %edi -0x8(%rbp)

- COPY a quad size (64 bits) register into memory
movq %rsi, -0x10(%rbp)

- COPY one register into another (pointer parameters are stored in %rdi)
movq %rax, %rdi

- COPY the byte 0x00 into register
movb $0x0, %al

- Call (system) function
callq 0x1000 00f6c

HAS ANYBODY ACTUALLY LOOKED AT WHAT THE CODE DOES?

That code will be looping for 1,500 years trying to iterate over every possible value between 1 and 2^64.

it is. it's fucking terrible.

Which registers are used as parameters for the printf statement?

Retard chiming in.

Last time I looked at assembly code it looked like this: Is the OP not x86? Or have there been changes?

en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI

>Isn't C supposed to translate quite closely to machine instructions

No, only retarded CS majors think that.

- COPY a quad size (64 bits) value (0x1) into memory (variable)
movq $0x1, -0x18(%rbp)

- COPY register into memory (conserve the value of this register while the register is being used to perform arithmetic operations)
movl %eax, -0x1c(%rbp)

- Compare quad value (0) with value in memory (sets equality flag)
cmpq %0x0, -0x18(%rbp)

- Jump if the equal flag is set (to xorl instruction)
je 0x1 0000 0f63

(else)
- Copy quad memory value to register
movq -0x18(%rbp), %rax

- Add quad value (1) to register
addq $0x1, %rax

- Copy register back to memory
movq %rax, -0x18(%rbp)

- Jump back to beginning of loop (back to cmpq instruction)
jmp 0x1 0000 0f42

It's AT&T style... some guys at AT&T thought it would be a good idea to make an alternative syntax for x86 assembly that's more like m68k assembly

while(
i64 != 0
)
What in the fuck do you think you're doing

Why do they call the copy instruction "move" when the data in the origin is not modified?

Different syntax

I did that to see if the debugger would step through the boolean expression so that I could see which assembly instructions were associated with it. It didn't work.

- XOR long value (effectively setting %eax to 0)
xorl %eax, %eax

- Add value (0x20) to register (restoring the sp)
addq $0x20, %rsp

- Restore bp (from stack, which was stored at the beginning of the function)
popq %rbp

- Return to calling function (in 64-bit mode, a return is conducted by popping a quad (64-bit) address back into %rip)
retq

* stack pointer increments downwardly (e.g. a pushed value will have a lower address than prior stack content)
base pointer %rbp pushed to stack
base pointer %rbp set to stack pointer %rsp
stack pointer %rsp subtracted by 0x20 (variable space)
load address of string into %rax
variable -0x04(l) set to 0
variable -0x08(l) set to value in register %edi
variable -0x10(q) set to value in register %rsi
address in %rax copied to %rdi (pointer parameter for printf)
register %al set to 0
printf system call
variable -0x18(q) set to 0
variable -0x1c(l) set to value in register %eax

loopStart:
variable -0x18(q) compared against 0
jump if equal flag set, to loopEnd
register %rax set to value in variable -0x18(q)
add 1 to register %rax
variable -0x18(q) set to value in register % rax
jump to loopStart
loopEnd:

register %eax xor'd against itself (effectively zeroing itself)
stack pointer added with 0x20 (removing variable space)
base pointer %rbp popped from stack
return to calling function

I need to know why the following instructions were in the OP:

variable -0x04(l) set to 0
variable -0x08(l) set to value in register %edi
variable -0x10(q) set to value in register %rsi

register %al set to 0

variable -0x1c(l) set to value in register %eax
register %eax xor'd against itself (effectively zeroing itself)


They appear to be superfluous to me but perhaps they have some actual purpose.

Bumping for this.

That would be an extra operation to clear the register for no real benefit.

I'don't really know x86 and all that jazz but here goes
movs to *rbp are moves onto the stack I presume.
my guess would be the first four things have to do with the printf call.
one of those 0 is probably the number of varargs, the other might be a nullpointer that would normally point to a buffer of arguments.

edi and rsi are probably caller saved registers that printf might overwrite

no idea what writing eax to the stack accomplishes or why it has to be zeroed, although eax might be used to pass return values, in that case the return value of printf maybe was saved on the stack for whatever reason and the eax was zeroed to return 0

layers upon layers of abstraction

It means, that there always exists an understandable mapping from c to Assembly. With understandable I mean, that it could be done by hand