NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: dominick on August 05, 2011, 07:15:54 AM
-
Hi,
I'm trying to take working code and turn it into a procedure using push and [esp] for the parameters... but all my code is doing is printing a blank line. I'm hoping that someone can explain how to push a string onto the stack and get it back as a parameter using [esp] - and how to push a number (string length) on to the stack and get it back using [esp + 4]. Also, I guess I would use 'Add esp, 4' to pop new values off of the stack?
Here's the non-working code:
org 0x100
[section .data]
string db "testing", 13, 10
strlen equ $ - string
message db "This is a message", 13, 10
messagelength equ $ - message
[section .text]
push word [string] ; Problem here?
call printstring
push word [message] ; Problem here?
call printstring
mov ax, 0x4c00
int 0x21
printstring:
lea si, [esp] ; Problem here?
xor bx, bx
strtoconsole:
lodsb
inc bx
cmp bx, strlen ; want to use [esp + 4] here.
je quit
mov dl, al
mov ah, 0x06
int 0x21
jmp strtoconsole
quit:
ret
... and here's the code that works:
org 0x100
[section .data]
string db "testing", 13, 10
strlen equ $ - string
message db "This is a message", 13, 10
messagelength equ $ - message
[section .text]
call printstring
mov ax, 0x4c00
int 0x21
printstring:
lea si, [string]
xor bx, bx
strtoconsole:
lodsb
inc bx
cmp bx, strlen
je quit
mov dl, al
mov ah, 0x06
int 0x21
jmp strtoconsole
quit:
leave
ret
If you have any problems understanding what I'm asking (I'm not feeling too clearheaded) I can make it clearer with some comments and rephrasing my question.
Thanks for your time,
Dominick
-
[org 100h]
[section .text]
push Text ; Push Text address
call PrintString
dec word [lenght]
push word [lenght] ; Push length variable value
call PrintLength
ret
PrintString:
; Proposit : Print a string passed by parameter in the stack
; In : Pointer to the string in the stack
; Out : None
; Destoys : None
push bp
mov bp, sp
mov dx, word [bp+4]
mov ah, 9
int 21h
pop bp
ret 2
PrintLength:
; Proposit : Prints a byte, from 0 to 9
; In : Number to be printed in the stack
; Out : None
; Destoys : None
push bp
mov bp, sp
mov dl, byte [bp+4]
or dl, 30h
mov ah, 2
int 21h
pop bp
ret 2
[section .data]
Text db "Hello,len$"
lenght dw $-Text
; > strings
; Hello,len9
-
org 0x100
[section .data]
string db "testing", 13, 10
strlen equ $ - string
message db "This is a message", 13, 10
messagelength equ $ - message
[section .text]
push word [string] ; Problem here?
Yeah. You've pushed "[contents]" - the letters 't' and 'e'. Lose the square brackets to push the address, which is what you want.
call printstring
push word [message] ; Problem here?
call printstring
Yeah, same problem. Also, the "call" intruction stores the return address on the stack(!), so the address of the string is at [esp + 2], not at [esp]. This ASSumes that esp = sp - the upper word of esp is zero. This is "probably" true.
mov ax, 0x4c00
int 0x21
printstring:
lea si, [esp] ; Problem here?
Yeah, "lea" (load effective address) puts the address of "[esp]" - just esp (= sp, we hope) in si. We want the "[contents]" of [esp] (= sp, we hope) - the address of our string... but it's at [esp + 2]... in si.
xor bx, bx
strtoconsole:
lodsb
inc bx
cmp bx, strlen ; want to use [esp + 4] here.
je quit
mov dl, al
mov ah, 0x06
int 0x21
jmp strtoconsole
quit:
ret
If I understand what you're trying to do...
org 0x100
[section .data]
string db "testing", 13, 10
strlen equ $ - string
message db "This is a message", 13, 10
messagelength equ $ - message
[section .text]
and esp, 0FFFFh ; make sure upper word of esp is clear!
push strlen
push string ; address of string
call printstring
add esp, 4 ; two parameters at two bytes each
push messagelength
push message
call printstring
add esp, 4
mov ax, 0x4c00
int 0x21
printstring:
mov si, [esp + 2] ; address
mov cx, [esp + 4] ; length
strtoconsole:
lodsb
mov dl, al
mov ah, 0x06
int 0x21
loop strtoconsole
quit:
ret
That's untested, but will "probably" work. What Alfonso showed you is probably better! His "ret 2" makes it a "stdcall" calling convention - callee cleans up stack. The plain "ret" and "add esp, 2 * number of parameters" makes it "cdecl" calling convention - caller cleans up stack. The Windows API uses stdcall - C uses cdecl. Since you're not using either, you have the choice of doing it either way (aren't choices nice? :) ).
Best,
Frank
-
Thanks Frank, avcaballero, your code has helped me to handle things cleanly.
Frank, it works perfectly. Avcaballero - the stdcall method of putting the number of used args after ret works like a charm.
Here's what I ended up with:
org 0x100
[section .data]
string db "testing", 13, 10
strlen equ $ - string
message db "This is a message", 13, 10
messagelength equ $ - message
[section .text]
and esp, 0FFFFh ; make sure upper word of esp is clear!
push strlen
push string ; address of string
call printstring
push messagelength
push message
call printstring
mov ax, 0x4c00
int 0x21
printstring:
mov si, [esp + 2] ; address
mov cx, [esp + 4] ; length
strtoconsole:
lodsb
mov dl, al
mov ah, 0x06
int 0x21
loop strtoconsole
.end:
ret 2
-
Good! But I think you want "ret 4" in this case - two parameters at 2 bytes each...
Best,
Frank