From: Frank K. <fbk...@co...> - 2003-10-12 19:20:06
|
Sean Champ wrote: > ...I'd ask if, & then, if so, how, the "Hello World" program would > need to be modified, for running it on Linux. Thanks for the kind words, Sean! I'm not really all that satisfied with that lame attempt at a "tutorial" (there was going to be more, but I got lazy), so it really pleases me when someone finds it useful (and/or amusing). To run under Linux, "almost everything" would need to be changed. "I don't think we're in Kansas anymore, Toto." The text "hello, world" can stay, but Linux uses just the linefeed (0Ah or 10 decimal), not a carriage-return/linefeed pair like dos to move to a new line. The damfool dollar-sign is *only* for dos int 21h subfunction 9 - no use anywhere else. The "sys-write" syscall expects to be told the length of the string to print, so the string doesn't need to be terminated in any way. It's probably worthwhile to write a routine that handles a zero-terminated string - like C - rather than keeping track of the length of everything. I just build a little "strlen" routine in-line that leaves the length in edx, but you could call a separate "strlen", too. Dos uses int 21h for almost everything, Linux uses int 80h. Dos puts the subfunction number in ah, Linux uses eax. The rest of the parameters go in registers. For sys_write, the "file descriptor" ("handle") goes in ebx - stdout is 1 (I'm told zero will also work), the "buffer" to write from in ecx, and the length in edx... ; nasm -f elf myprog.asm ; ld -o myprog myprog.o global _start section .text _start mov eax, 4 ; the "sys_write" subfunction mov ebx, 1 ; the "file descriptor - stdout mov ecx, msg ; the address of the message mov edx, msg_len ; how many bytes to write int 80h ; call kernel services mov eax, 1 ; the sys_exit subfunction mov ebx, 0 ; the exit code - 0 = no error int 80h ; call kernel services section .data msg db 'Hello, world',0Ah msg_len equ $-msg It has come to my attention that this isn't very "robust". I've never seen it, but I've been informed (by hpa, and he outta know!) that it can be interrupted before it's finished and won't print the whole "length". Here's "lnxhello.asm" fron Nasm's "test" directory, which copes with that. ; ; Assembly "Hello, World!" for Linux ; ; Properly defined in <sys/syscall.h> %define SYS_exit 1 %define SYS_write 4 section .text global _start _start: ; gdb doesn't like to stop at the entry point address, so ; we put a nop here for pure convenience nop write_hello: mov edx, hello_len mov ecx, hello .loop: mov eax, SYS_write mov ebx, 1 ; stdout int 80h cmp eax, -4096 ja error add ecx, eax sub edx, eax jnz .loop ok: mov eax, SYS_exit xor ebx, ebx int 80h hlt error: mov eax, SYS_exit mov ebx, 1 ; Error int 80h hlt section .rodata hello: db "Hello, World!", 10 hello_len equ $-hello I have no idea how we'd test this to make sure it actually works... The "$" in the "length" expression maybe needs some explaining... It's the "here" symbol, and evaluates to the current "location counter" in the file. In other words, "where we are now", minus "where we were when the message started" gives the length... (incidentally "$$" indicates the start of the section, so "$ - $$" gives the length of the code so far) That's about all I can think of at the moment. Sorry for the delayed reply - I've had the thing in my "drafts" folder for about a week. I think I'll cc this to the newly-created "nasm-users" list on SourceForge - just so it won't be *entirely* Windows :) http://lists.sourceforge.net/lists/listinfo/nasm-users - please join us, if you're so inclined. Again, thanks for the feedback! Best, Frank |