A few x86_64 assembly tips #87
Replies: 1 comment 1 reply
-
You are correct.
Regarding a rewrite to C. You may want to look into using Limine as the boot loader. I tried this earlier in the week and it was pretty straightforward - https://github.com/limine-bootloader/limine-c-template |
Beta Was this translation helpful? Give feedback.
-
1 - Don't push the same register multiple times.
push rax
push rax
do something
pop rax
do other stuff
pop rax
Instead:
push rax
do something
mov rax, [rsp] ; take the value from the top of the stack
do other stuff
pop rax
If you need access to the next item on the stack, then [rsp+8] will do.
2 - Write position independent (relocatable) code:
I - lea register, [symbol] instead of mov register, symbol
II - put: "DEFAULT rel" in the top of the file, and all accesses like mov register, [symbol] become rip relative without having to change the code. But you need to use [abs symbol] when symbol if fixed in memory rather than a symbol inside the same binary. For instance: call [abs b_output]. LEA using relative address saves a few bytes per instruction (because the relative addressing is 4 bytes wide vs 8 bytes when you load an abs address into a register).
III - If you do it right, the ORG directive becomes irrelevant.
I'm converting monitor and tools to relocatable code. As soon as I'm done I'll post the code.
3 - You can multiply a register on the fly for relative addressing, saving some instructions.
mov rax, [rbx+rsi * 8]
mov [rcx+rdi * 8+offset], rdx
Only rsi and rdi can be multiplied, and only by 1,2,4,8.
https://blog.yossarian.net/2020/06/13/How-x86_64-addresses-memory
Unrelated:
I've been converting BareMetal code to C. My current code is really ugly, so I'm not ready to share yet, I've got AHCI,IDE and E1000 drivers working. With interrupts for AHCI. I can glance at C code and understand exactly what it does, but assembly is so much harder to read.
Beta Was this translation helpful? Give feedback.
All reactions