Key Concepts
- Assembly language learning through unscripted coding sessions.
- XOR cipher implementation in assembly.
- Minimal bootloader creation in assembly for BIOS systems.
- 16-bit real mode programming.
- BIOS interrupts for screen output.
- Segment registers (CS, DS, ES) and their role in memory addressing.
- Index registers (SI) for string manipulation.
- Boot sector structure (512 bytes, boot signature).
- QEMU for bootloader testing.
XOR Cipher Implementation
Goal
Implement an XOR cipher where user input from stdin is XORed with a static mask, and the result is printed to stdout. The process should be reversible using the same mask.
Steps
- Project Setup: Create a file named
exorcipher.asmand define the.textsection withstartas the entry point. - Input Buffer: Allocate a 32-byte buffer in the
.bsssection namedinput_bufferusingresb 32. - XOR Mask: Define a 32-byte static XOR mask in the
.datasection namedkeyusingdb "My fancy key for the cipher in asse". - System Call for Input:
- Move
0intorax(syscall number forsys_read). - Move
0intordi(file descriptor for stdin). - Move
input_bufferintorsi(pointer to the input buffer). - Move
32intordx(number of bytes to read). - Execute
syscall.
- Move
- Register Allocation:
rsi: Pointer toinput_buffer.rdi: Pointer tokey.r8: Pointer toresult_buffer(allocated usingresb 32in.bss).
- XOR Loop:
- Move
4intorcx(loop counter, since we process 8 bytes at a time). - Load 8 bytes from
input_bufferintoraxusingmov rax, [rsi]. - Load 8 bytes from
keyintorbxusingmov rbx, [rdi]. - XOR
raxandrbxusingxor rax, rbx. - Store the result from
raxintoresult_bufferusingmov [r8], rax. - Increment
rsi,rdi, andr8by 8 usingadd rsi, 8,add rdi, 8, andadd r8, 8. - Decrement
rcxusingloop xor_loop.
- Move
- System Call for Output:
- Move
1intorax(syscall number forsys_write). - Move
1intordi(file descriptor for stdout). - Move
result_bufferintorsi(pointer to the result buffer). - Move
8intordx(number of bytes to write). - Execute
syscall.
- Move
- Exit:
- Move
60intorax(syscall number forsys_exit). - Move
0intordi(exit code). - Execute
syscall.
- Move
Key Points
- Registers can only hold 8 bytes (64 bits), so the 32-byte input is processed in four 8-byte chunks.
- The
loopinstruction decrementsrcxand jumps to the specified label ifrcxis not zero. - Square brackets
[]are used to dereference memory addresses.mov rax, [rsi]loads the value at the address pointed to byrsiintorax. - The XOR operation is symmetric, meaning applying it twice with the same key restores the original data.
Example
If the input is "hello wo" and the key is "My fancy", the XORed output will be a series of non-printable characters. Feeding this output back into the program with the same key will restore "hello wo".
Python Verification
Python can be used to verify the XOR cipher:
key = "My fancy"
message = "hello wo"
keyb = key.encode('ascii')
messageb = message.encode('ascii')
result = bytes(x ^ y for x, y in zip(keyb, messageb))
print(result.decode('ascii', errors='ignore'))
Minimal Bootloader Implementation
Goal
Create a minimal bootloader that prints "Hello World!" to the screen when the system boots, without relying on an operating system.
Steps
- Environment Setup:
- Specify 16-bit real mode using
bits 16. - Set the origin to
0x7c00usingorg 0x7c00.
- Specify 16-bit real mode using
- Segment Register Setup:
- Disable interrupts using
cli. - Push the code segment register
csonto the stack usingpush cs. - Pop the value from the stack into the data segment register
dsusingpop ds.
- Disable interrupts using
- Message Definition:
- Define the message "Hello World!" in the code section using
message db "Hello World!", 0. The0is a null terminator.
- Define the message "Hello World!" in the code section using
- Print Loop:
- Load the address of the message into the source index register
siusingmov si, msg. print_loop:label:- Load a byte from the address pointed to by
siinto thealregister usinglodsb. - Test if the value in
alis zero usingtest al, al. - If it is zero, jump to the
donelabel usingjz done. - Move
0x0einto theahregister (BIOS teletype function) usingmov ah, 0x0e. - Call the BIOS interrupt
0x10usingint 0x10. - Jump back to the
print_looplabel usingjmp print_loop.
- Load a byte from the address pointed to by
- Load the address of the message into the source index register
- Halt:
done:label:- Disable interrupts using
cli. halt:label:- Halt the CPU using
hlt. - Jump back to the
haltlabel usingjmp halt.
- Halt the CPU using
- Disable interrupts using
- Padding and Boot Signature:
- Pad the remaining bytes with zeros using
times 510 - ($ - $$) db 0. - Add the boot signature using
dw 0xaa55.
- Pad the remaining bytes with zeros using
Key Points
- 16-bit Real Mode: The bootloader operates in 16-bit real mode, which has a segmented memory model.
- BIOS Interrupts: The bootloader uses BIOS interrupt
0x10to print characters to the screen.ah = 0x0especifies the teletype function. - Segment Registers: In real mode, memory addresses are calculated as
segment * 16 + offset. The code segmentcsand data segmentdsmust be properly set up. - Boot Signature: The last two bytes of the boot sector must be
0xaa55for the BIOS to recognize it as a bootable sector. lodsbInstruction: This instruction loads a byte from memory (pointed to bysi) intoaland incrementssi.cliandhlt:clidisables interrupts, andhlthalts the CPU.
Assembly and Testing
- Assemble: Use NASM to assemble the code into a binary file:
nasm -f bin bootloader.asm -o bootloader.bin. - Create Floppy Image: Use
ddto create a floppy image:dd if=/dev/zero of=floppy.img bs=512 count=2880. - Write Bootloader to Image: Use
ddto write the bootloader to the floppy image:dd if=bootloader.bin of=floppy.img bs=512 count=1 conv=notrunc. - Test with QEMU: Run the bootloader in QEMU:
qemu-system-i386 -fda floppy.img. UseCtrl+A Xto exit QEMU.
Troubleshooting
- Triple Fault: A triple fault indicates a serious error in the bootloader code, such as an invalid instruction.
- VirtualBox Crashes: VirtualBox may crash due to system-specific issues. QEMU is a more reliable option for testing bootloaders.
Conclusion
The session successfully implemented an XOR cipher and a minimal bootloader in assembly. The bootloader was tested using QEMU, demonstrating the ability to print "Hello World!" without an operating system. The session highlighted the complexities of low-level programming and the importance of understanding memory addressing, segment registers, and BIOS interrupts.
AI summaries can miss context or contain errors. Check important details against the original video.





