; write5.asm: similar to write4.asm, but will detect whether it is being run on Linux, FreeBSD, or OpenBSD
; linux puts 0x00 in FS and GS, FreeBSD puts 0x2f, and OpenBSD puts 0x1f. Why? No idea - look into it.
SEGMENT .text
xor ebx, ebx ; Zero registers
mul ebx ;
mov cx, fs ; Put the value in fs into cx
cmp cl, 1fh ; Check if the value in cx is 0x1f
jz short openbsd ; If it is, jump to openbsd
cmp cl, 2fh ; Check if the value in cx is 0x2f
jz short freebsd ; If it is, jump to freebsd
cmp cl, al ; Check if the value in cx is 0
jz short linux ; If it is, jump to linux
jmp short unknown ; not any of the ones we expect,
continue:
mov dl, 8 ; put the value 8 into edx (size_t len)
jmp short end ; let's finish this off, no more preperation needed
continueGNU:
mov dl, 6 ; put the value 6 into edx (size_t len) and continue down to end
end:
mov al, 4 ; put the value 4 into eax (syscal number of write)
inc bl ; increment ebx to 1 (stdout, int fd)
pop ecx ; pop the pointer to our string (old eip) off the stack into ecx
push edx ; push edx onto the stack for BSD
push ecx ; push ecx onto the stack for BSD
push ebx ; push ebx onto the stack for BSD
push eax ; push eax onto the stack for BSD
int 80h ; enter kernel mode
mov al, 1 ; put the value 1 into eax (syscall number of exit)
dec ebx ; decrement the value in ebx to 0 (int status)
push ebx ; push ebx onto the stack for BSD
push eax ; push eax onto the stack for BSD
int 80h ; enter kernel mode
openbsd:
call continue ; call the continue section
db 'OpenBSD', 10 ; as the return value (\0x0a is \n)
freebsd:
call continue ; call the continue section
db 'FreeBSD', 10 ; as the return value (\0x0a is \n)
linux:
call continueGNU ; call the continueGNU section
db 'Linux', 10 ; as the return value (\0x0a is \n)
unknown:
call continue ; call the continue section
db 'Unknown', 10 ; as the return value (\0x0a is \n)