NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: nobody on December 28, 2007, 06:03:08 PM
-
I'm try to print a command line argument to STDOUT, and print "Hello World"; using libcs' printf, and the other using a system call. But for some reason, the formating doesn't come out atall when I do this.
I've been sat here for about two hours trying to figure it out, any help would be great. The output I get is this:
bt nasm # ./prog argument
Argv[1] == \
Hello World
Instead of "Argv[1] == argument" I get "Argv[1] == \"
I reckon it's something todo with this:
pop ebx ; pop argc
pop ebx ; pop argv[0]
pop ebx ; pop argv[1]
But I'm not 100% sure.
-------------------------------------------
extern printf
section .data
fmt: db "Argv[1] == %s", 10, 0
msg: db "Hello World",10 ; the string to print
len: equ $-msg ; "$" means "here"
section .bss
section .text
global asm_main
asm_main:
push ebp
mov ebp, esp
pop ebx ; pop argc
pop ebx ; pop argv[0]
pop ebx ; pop argv[1]
mov edx, ebx ; move argv into edx
mov ecx, fmt ; move string pointer into ecx
push edx
push ecx
call printf
mov edx,len ; arg3, length of string
mov ecx,msg ; arg2, pointer to string
mov ebx,1 ; arg1, where to write, screen
mov eax,4 ; write(int fd, const void *buf, size_t count)
int 0x80 ; interrupt 80 hex, call kernel
add esp, 8
mov esp, ebp
pop ebp
mov eax, 1
int 80h
Thanks in advance!
-
global asm_main
asm_main:
push ebp
mov ebp, esp
pop ebx ; pop argc
pop ebx ; pop argv[0]
pop ebx ; pop argv[1]
Ahhhh... If "asm_main" is being passed to ld as "--entrypoint", you've got argc, arg[0](name), arg[1](first parameter, if any), ...
However! You've pushed ebp, so your first pop is just getting ebp back, second pop would be argc... However! This looks like it might have been called by a C startup stub (Dr. Carter's tut?)... in which case you've popped the return address (doesn't matter, since you "sys_exit" instead of "ret"ing). Lord knows what the next pop will fetch...
What *I* would do, is to replace "asm_main" with "_start" (ld's default entrypoint). Assemble as usual, but you'll need to tell ld where to find the "right" dynamic linker (ld gets it wrong, by default - gcc knows...):
ld -o myprog myprog.o -I/lib/ld-linux.so.2 -lc
(by default, ld looks for .so.1 which results in a "file not found" when you do ./myprog - most puzzling!)
Also, drop the push ebp/mov ebp/esp... Start right with the pops. The first pop will be argc - you may wish to check this, to see if the user entered any parameters. There will be at least one - the program name. The next pop will be that - you'll probably discard it. The next pop should be (pointer to) "argument". As an alternative to checking argc, you can check this for non-zero... really "should" make sure we've got an argument, before we try to print it. From there on, I think you've got it right. You can just push ebx/push fmt - no *need* to put 'em in separate registers. (I'd do the add esp, 8 immediately after call printf, for clarity...)
If this is, in fact, called by Dr. Carter's driver.c... all bets are off. Lessee... "main" is called by crt0... stack would be return (to crt0) address... pushed ebp... a local variable "ret_ status" (who knows what gcc allows for a single dword), return (to main) address, your pushed ebp... You don't want to do this by poppin' stuff!!! Try something like mov ebx, [ebp + ???]... increase ??? by four until you find it. :)
You've got a linefeed (10) in your format string. Good. As an experiment, try removing it... "Hello World" will print *before* "argument"! Printf doesn't actually print anything until its internal buffer is flushed - either by a linefeed, or by exit. Just a tip...
Best,
Frank
-
Thanks Frank, that's a wealth of info! I'm kind of getting the hang of this. I've found quite alot of stuff online that have seriously helped (you of course) and these (for anyone else reading this):
nasm x86 Assembly Quick Reference ("Cheat Sheet")
http://www.cs.uaf.edu/2007/fall/cs301/support/x86/index.html (http://www.cs.uaf.edu/2007/fall/cs301/support/x86/index.html)
Extending NASM with Macros
http://www.codebreakers-journal.com/content/view/158/104/ (http://www.codebreakers-journal.com/content/view/158/104/)
And do a google like so: site:www.codebreakers-journal.com nasm
Say if I wanted to use GCC (which I generally do), what would I have to use instead of _start? (last question).
I can feel this week/month/year is going to be filled with me obsessing over NASM code. ;)
bt nasm $ vi first.asm
bt nasm $ nasm -f elf first.asm
bt nasm $ ld -o myprog first.o -I/lib/ld-linux.so.2 -lc
bt nasm $ myprog
Usage: ./prog argument
bt nasm $ myprog sdf
Argv[1] == sdf
Hello World
bt nasm $
Thanks Frank.