At the beginning we push rbp and save rsp in rbp. Then on the top of then stack (and at %rbp) we've got saved rbp. Then everything below rbp is free space.

But then we place passed parameters from edi and esi at -0x14(%rbp) and below.

But why can't we put them immediately below what rbp/rsp points at?edi and esi are 4 bytes long, why not -0x8(%rbp) and -0xc(%rbp), then? Is it connected with memory alignment?

And why is there a weird saving eax to stack and reading it back before return?

Best How To :

First of all, please note that you're looking at unoptimized compiler output. Compiler output often ends up looking kind of stupid with optimizations turned off because the compiler literally translates every line of C into an equivalent run of assembly without bothering to even do the simplest, most obvious optimizations.

For your first question, the answer is "because that's where your compiler decided the variables should go". There's no better answer - compilers differ widely in their stack allocation schemes. For example, Clang on my machine outputs this instead:

where you can see clearly that a gets stored at -4, b gets stored at -8, and result is stored at -12. This is a tighter packing than what your GCC is giving you, but this is just a quirk of GCC and nothing more.

For your second question, let's just look at how the instructions map to C:

So you can see that the redundant saving and loading of eax is simply because the save and load correspond to different statements of your original C file: the save is from result = and the load is from return result;.

Much smarter: no stack manipulation, and the entire function body is just the two instructions addl and movl. (Of course, if you declare the function static, then both GCC and Clang will happily detect that the function is never productively used and simply delete it outright.).

jmp *%eax is AT&T syntax for jmp eax, which is one form of jmp r/m32. It will jump to the address contained in register eax: Jump near, absolute indirect, address given in r/m32. Another form of the same type of jump instruction is jmp *(%eax) which corresponds to jmp [eax]...

The value in R8 at the time your program crashes is the file descriptor returned by the open syscall. Its value is probably 3 which isn't a valid address. You'll need to stores these values in a range of memory you've properly allocated. You can create a buffer in your...

The assembly file is meant to be run through the C preprocessor before being sent to the assembler. This should result in the C macro being properly expanded, assuming that the macro been defined in the one of the other files that are included by the #include lines. To have...

The problem with creating shellcode from C programs is not that you cannot control the assembly generated, nor something related with the code generation. The problem with creating shellcode from C programs is symbols resolution or relocation, call it whatever you like. You approach, for what I have understand, is...

There simply is no such form of je. What you can do is put a relative conditional jump based on the opposite condition, followed by an unconditional register-indirect jump: jne skip jmp eax skip: You could make a macro out of this to save you from writing the same thing...

The inline assembly make use of a feature of Linux kernel that allow developer to "catch" CPU exceptions. The instruction at label 1 is a XRSTOR (more on this later). The code at label 3 is emitted in the .fixup section that contain code used to handle exceptions. The _ASM_EXTABLE...

Some mistake I found is: In GETLIST: sw $v0,0($a2) #store in array add $a0,$a0,4 #next number <= instead write 'add $a2,$a2,4' if you want don't want to overwrite it. Also the problem in printing list is that you are adding $a2 to store the number in the array. But, you...

Java uses bytecode. The most similar would be javap, per the linked Oracle documentation, the javap command disassembles one or more class files. Its output depends on the options used. package com.stackoverflow; class Main { public static void main(String[] args) { System.out.println("Hello, World!"); } } If I compile that to...

The lodsb instruction loads the byte pointed to by the DS and SI registers but you haven't loaded either with a valid value. Since this a bootloader you also need to use the ORG directive, otherwise the assembler won't know where you code, and therefor welcome, gets loaded into memory....

div di divides the 32 bit quantity dx:ax by di. We don't know what value your bx has, but presumably it produces dx=1 (due to the adc dx, dx). So the division is going to be 0x10003 / 3 = 0x5556 remainder 1, and that's exactly what you see. PS:...

Your first instruction is the problem: cmp rdi, 0. You're comparing the string pointer, passed to my_puts, to the value 0 to determine if you should print "(null)" rather than comparing the first byte of the string to 0. I'm supposing if you pass a 0 pointer, that would be...

When a string is captured from keyboard with int 21h, ah=0Ah, the string has next structure: As you can see, the first two bytes are control, the characters entered by user start at the third byte (byte 2). The last char is chr(13) (ENTER key). To display this captured string...

Variables created in the .data section are directly accessable from every procedure. LOCAL variables are only present in the specific procedure and getting popped from the stack as soon as the procedure ends. What do you mean exactly with "end up with a random value"?

Somewhat ironically, by using UAL syntax to solve the first problem you've now hit pretty much the same thing, but the other way round and with a rather more cryptic symptom. The only Thumb encodings for (non-flag-setting) mov with an immediate operand are 32-bit ones, however Cortex-M0 doesn't support those,...

The subl $16, %esp is a red herring. The actual issue is in print_int: movl value(%ebp), %eax jge .L1 # if value >= 0 movl doesn't set flags. You are missing a test %eax, %eax or equivalent before the jge. Learn to use a debugger. It would have pointed you...

There is no simple answer, so I won't delve into it here. You have to peek into the FAT (File Allocation Table) structures on the disk: https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system More, Reference: https://en.wikipedia.org/wiki/File_Allocation_Table...

That method is called, "Division by Invariant Multiplication". The constants that you're seeing are actually approximates of the reciprocal. So rather than computing: N / D = Q you do something like this instead: N * (1/D) = Q where 1/D is a reciprocal that can be precomputed. Fundamentally, reciprocals...

The problem is, you don't have debug info for the ptr type, so gdb treats it as integer. You can examine its real contents using: (gdb) x/a &ptr 0x600124 <ptr>: 0x7fffffffe950 (gdb) p/a $rsp $3 = 0x7fffffffe950 Of course I have a different value for rsp than you, but you...

To access any individual element of array, you can use it as: la $t3, array # put address of array into $t3 If array is a byte array, like: array: .byte 'H','E','L','L','O' to access the ith element: lb $a0, i($t3) # this load the byte at address that is (i+$t3)...

IA32 processors have a default code size, in 16 bit code segments (or in real mode) is (guess) 16 bit. In 32 bit and 64 bit code segments it is 32 bit. Instructions like mov eax, 3ch are actually something like mov A, 3ch where A is the A register...

mov dword ptr [rsp + 20h], 0 is wrong. The last parameter has the type LPOVERLAPPED, which is here a 64-bit pointer. Change the line to mov qword ptr [rsp + 20h], 0 Also, lea rcx, handle is wrong. WriteFile expects a value, not an address (pointer). Change it to...

The problem is that INT 16h AH=00h returns a ASCII character code in AL and an scan code in AH. The mov [qbuf], ax instruction stores both in the buffer, but INT 10h AH=0Eh only prints ASCII characters. It ends up interpreting the scan code you stored in the buffer...

Your compilation isn't including anything from ncrs.cpp, which is where both NCRS::Start() and NCRS::End() are defined. You probably want clang++ crspro.cpp ncrs.cpp -lncurses -o crspro Or if you want to build the object files separately and then link them: clang++ -c crspro.cpp -c clang++ -c ncrs.cpp -c clang++ crspro.o ncrs.o...

Conditional branches are I type instructions, they have 16 bit immediate field. If the condition is met, PC is updated as PC += immediate << 2. PC is the address of the conditional jump. The immediate is a two complement value (to jump back eventually), so the range is from...

You cannot use compiler intrinsics because they are processed by the Delphi compiler rather than the assembler. Intrinsics are resolved by the Pascal compiler processing and parsing Pascal expressions, and then emitting code. That's the job of a compiler rather than an assembler. At least, that's my mental model. In...

The type int can only hold a 16-bit signed integer and the number you tried to assign to filename is way outside its range. As int variables are two bytes long, they're not all that useful for storing file names. Instead you should store the name in an array of...

I don't think there's any way to convince the OpenWatcom compiler to emit a group based segment relocation. Part of the problem is that there's no way to declare or define the group so that you can refer to it in the inline assembly. However, it appears the OpenWatcom linker...

Your hex dump is just a bunch of function names so it doesn't tell us much. And you didn't mention an operating system either... I'll assume if you can run gdb on it, you can use GNU binutils too. For a start you can try objdump -h myprog. It will...

AVX is disabled because the entire AMD Bulldozer family does not handle 256-bit AVX instructions efficiently. Internally, the execution units are only 128-bit wide. So 256-bit operations are split up thereby providing no benefit over 128-bit. To add insult to injury, on Piledriver, there's a bug in the 256-bit store...

Here's an example from a course that I teach. This is a raw bootsector that you can compile directly as an object file and use as a bootable floppy or USB image in something like Qemu, VirtualBox, VMWare, Bochs or a real machine. This makes use of the real mode...

Old MinGW versions had the problem that "ld" was not able to create non-PE files at all. Maybe current versions have the same problem. The work-around was creating a PE file with "ld" and then to transform the PE file to binary, HEX or S19 using "objcopy"....

To define a string you can use the .STRINGZ directive, which also places the terminating zero after it. You should use BRNZP because the assembler apparently doesn't like BRZNP. Other than that, your code works fine.

The immediate problem is that your prints destroys bx (because it sets bl and bh) so your printmem loop which requires bx to be preserved blows up. However, it also destroys al so your input loop won't be storing the correct value in memory to start with, either. Furthermore, while...

Is "$32" means 32 bytes ?($number means constant ?) If yes then how are we allocating 32 bytes on 64 bit register? These 32 bytes are not allocated on 64 bit register. They are allocated on the stack. By lowering the stackpointer (which is in %rsp) the address range...

Thanks for your advice knm241. The above program now works fine thanks to you. The only problem that occurred was that the keyboard buffer was not clearing and thus the program would get stuck in a loop. I fixed that by clearing the buffer and now everything works. I used...

Your code does have a main function, which is required for it to work. As you said the debugger returned a 'missing executable' error, I'm assuming you didn't compile the code, or if so, got some errors which can be found in the output and error windows. If you're working...

All of these operations in your code are incorrect: mov[num1 + eax-3], 0 StdIn returns the number of characters read, excluding the NUL terminator. So if you entered 100, eax will be 3, so you'll set the very first byte to 0, thereby making num1 an empty string. Even worse,...

Unlike A32's "flexible second operand", there is no common immediate format in A64. For immediate-operand data-processing instructions (ignoring the boring and straightforward ones like shifts), Arithmetic instructions (add{s}, sub{s}, cmp, cmn) take a 12-bit unsigned immediate with an optional 12-bit left shift. Move instructions (movz, movn, movk) take a 16-bit...

The DEFINE_ARGS macro defines a number single line macros the are meant to be used to refer to the arguments of the function that the cglobal macro introduces. So for example, if foo is given as the name of the first argument then DEFINE_ARGS creates the following defines: %xdefine fooq...

In MASM the label MY_VAR translates to the offset part of the address of MY_VAR relative to the segment it was declared in (if you use it like mov ax, MY_VAR) or relative the to segment you have assumed for the segment register you are using to access it (if...

The fault is caused because the mouse interrupt 33h function AX=0003h returns the mouse position in CX and DX. This overwrites your "counter" in register CX. It is always a dangerous game to keep values in registers throughout a program. Better to have a memory variable location. You could also...