💾 Archived View for gem.librehacker.com › gemlog › tech › 20220222-0.gmi captured on 2024-08-18 at 17:46:45. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-03-01)
-=-=-=-=-=-=-
The adventure continues... I have been uploading my little practice exercises to a public repo, in the off-chance someone might find them useful:
https://codeberg.org/infrared/x86-64-as-practice
The last one I did is called multiple.s, which checks whether or not either of two numbers are a multiple of the other. Some things I've learned in the process:
Before starting to learn assembly programming, I never had used the GNU debugger for anything, unless I was forced to use it to send in a bug report. But I use it frequently now to check the registers or memory values at a given point in program execution. My most commonly used commands:
- 'file ./somefile' to load up an executable
- 'run' to run the program
- li [linenumber] to list the source code
- 'b linenumber' to set a breakpoint
- 'clear' to clear breakpoints
- 'i r' to view the register values
- 'p (type) memory_label' to view the memory value at a label
- 'step' to step to the next instruction
- 'layout asm' to set up a half-screen display of the instructions
Something you have to be aware of in x86-64 assembly programming is memory alignment. Mainly, you are concerned about this when calling libc functions, which expect the stack to be 16-byte aligned. Your stack starts off aligned, but the tricky part is that calling a function adds an extra 8 bytes onto the stack (the return address). So you might need to add extra bytes on the stack before you make the call. A common trick is "push %rdp", and then remember later to "pop %rdp". If you don't take care of this, the procedure you call might segfault on an SSE instruction or something like that.
I thought it was interesting to learn that the 'div' instruction, for dividing unsigned integers, uses a 64 bit divisor, but the dividend is two registers, i.e., 128 bits. So, if you want just a 64 bit dividend, then you have to clear the "top" register.
You've got three options:
- The /* */ syntax, great for commenting multiple lines
- The hash (#)
- The forward slash (/)
The third option should be avoided due to possible confusion with division operations. The second option is best for single line comments, though you have to be carefully as it has some special meaning when it is the first character on the line (preprocessor directives and logical line numbers: see section 3.3 in the info manual).