Author Topic: printf issues  (Read 8225 times)

nobody

  • Guest
printf issues
« 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!

nobody

  • Guest
Re: printf issues
« Reply #1 on: December 28, 2007, 08:35:12 PM »
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

nobody

  • Guest
Re: printf issues
« Reply #2 on: December 29, 2007, 12:27:46 PM »
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

Extending NASM with Macros
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.