; 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)