My setup
- OS: ------------------ Linux
- Architecture: ------ x86-64
- Syntax: ------------ AT&T
- Compiler: --------- GAS
My code
(explanation below)
.section .text
.globl _start
print:
movq $1, %rax
movq $1, %rdi
movq %rsp, %rsi
popq %rbx
popq %rdx
# Useless Instructions...
xor %rcx, %rcx # 36
xor %rcx, %rcx # 39
xor %rcx, %rcx # 42
xor %rcx, %rcx # 45
xor %rcx, %rcx # 48
xor %rcx, %rcx # 51
xor %rcx, %rcx # 54
xor %rcx, %rcx # 57
xor %rcx, %rcx # 60
xor %rcx, %rcx # 63
xor %rcx, %rcx # 66
syscall
jmp end
ret
_start:
pushq $66
pushq $1
call print
end:
movq $60, %rax
xor %rdi, %rdi
syscall
Output: "B"
Explanation
Okay here comes the thing. As you see, I want to:
- Push
$66
($'B'
) to the stack - Call the
print
function - Mov the
$66
into the%rsi
register - Write to
STDOUT
with the linuxsyscall 1
, which is the linux _write syscall - Jmp to the end label, otherwise the
Error: segmentation fault (core dumped)
gets raised
What's wrong
I expect it to output "B", which it does. So where is the problem you may ask? You probably already saw that bunch of xor %rcx, %rcx
's.
Let me explain what they do:
- For some reason it starts at
33
("!") - For every instruction I add to this code, it adds
3
to this number - So I added
11
instructions, and the33
became66
(33 + 11*3 = 66), which is "B" in ASCII
Without the 11 xor
-instructions, it prints "!" which has the ASCII value of 33.
Note: xor %rcx, %rcx
is just some instruction. It can be every instruction and every instruction has the value of 3
.
That means
I can add as many instructions as I want, to print every ASCII value over 33.
Example:
If I want to echo an "H", all I have to do is to add 2 more xor %rcx, %rcx
instructions.
Calculation: 66
("B") + 3
(1 instruction) + 3
(1 instruction) = 72
("H")
Final Question
Why? Just why? I just started with x86 ASM
, so I am completely new to it. There are clearly some obvious things I am missing here... I just played around a bit and stumbled across this.
Can you help me answer these questions?
- How does it work?
- How can it affect the output / RSI register?
- Why does it start at 33?
- Any ideas on how to fix this?
My guess is, it has to do something with the Instruction Pointer, but I have no clue...
Thank you for your help :)