NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: isywum on July 01, 2012, 05:36:06 PM
-
Hi,
I was writing a function that does something with an userdefined string. I do not know how I can transfer the paramter. I can't just push it. I checked up how this problem is solved in C. C just writes the string to an adress and transfers the pointer (char*). So I tried to write the string to an adress thereabout:
mov [0x14000], "That's an example."
Of course it does not work. Do you have any suggests to solve that problem?
-
There are a few different ways to do this, but here is one example
String db 'Thats an example.', 0
push String
call Function
Function:
push ebp
mov ebp, esp
mov edi, [rbp+8] Now edi = pointer to String
.... You code
leave
ret
Quite a bit is missing from this example, but it's analogous to:
void Function (char *String);
-
Thanks.
Just a question:
Did you mean 'rbp' or 'ebp'?
-
Did you mean 'rbp' or 'ebp'?
Yes, ebp. I usually work in 64 bit.
-
I thought "push reg32" was invalid in 64-bit code? I'm confused! (what else is new?)
In any case, Isywum, you generally want to pass the address of the string as a parameter - 32-bit or 64-bit... 16-bit if we want to go back to the dark ages. You could subtract "enough" from esp/rsp and copy the actual string onto the stack, but it is not usually useful...
Best,
Frank
-
I thought "push reg32" was invalid in 64-bit code?
Yes it is, but to excuse it by saying I usually work in 64 bit was just another way of saying I wasn't paying attention :'(
32 bit cdecl
push String
call Function
add esp, 4
Function:
push ebp
mov ebp, esp
mov edi, [rbp+8] Now edi = pointer to String
.... You code
leave
ret
32 bit stdcall
push String
call Function
Function:
push ebp
mov ebp, esp
mov edi, [rbp+8] Now edi = pointer to String
.... You code
leave
ret 4
64 bit using EDI is not an error. 32 bit registers are sign extended to 64 and I know, or at least on my system all segments except stack are below 32 bit boundary.
mov edi, String
call Function
Function:
.... You code and RDI points to string
ret
Hopefully this doesn't thoroughly confuse the issue isywum, but in principal these are equivalent. The thing to remember is, the arguments you pass to procedure start @ word width * 2. above base pointer being either RBP or EBP. As Frank pointed out IF you are working in 16 bit then remove "E"'s and in the first two examples, 4's are replace with 2's
NOTE: When asking a question, it is always a good idea to qualify which platform you're working in and how many bits. This gives us the opportunity to narrow the answer exactly to your criteria.
-
Thank you. This helps me but is it also possible to write the string to an user-defined address?
EDIT:
I use Bits 32.
-
Thank you. This helps me but is it also possible to write the string to an user-defined address?
Here again it's important than you specify your platform target since the best practice in this case is reserving dinamic memory(if user input the string, how long will be?) then is the operating system who decides where alloc memory through api call GlobalAlloc,LocalAlloc wrappers of HeapAlloc / VirtualAlloc on windows, brk system function under unix-like, etc. This functions return a pointer to the allocated memory so you can now pass it to your function and write the string.
(Alloc memory)
push String
push eax ;pointer to memory
call Function
Function:
push ebp
mov ebp, esp
mov esi, [ebp+8] ;Now esi = pointer to String
mov edi, [ebp+c] ;Now edi = pointer to Memory
cld
rep movsb ; copy string
.... You code
leave
ret
remember to free the reserved memory after done.
Answering your question yes it can be achieved but would be impractical after all the user doesnt mind where is the string in memory
Regards.
-
I forgot to tell you ... I write a little OS myself. So it is important ...
-
I write a little OS myself. So it is important ...
Essentially no, as what we are talking about here is a method by which memory is addressed and/or its contents. So to move a byte from a memory location to AL is the same no matter the system so long as it's using the same processor and not only that, but there are usually several different ways of doing it.
Here's an example in pure binary format
1 [BITS 32]
2
3 00000000 A0[0D000000] mov al, [Msg] AL = 54H
4
5 00000005 BE[0D000000] mov esi, Msg ESI = 000DH
6 0000000A 8A06 mov al, [esi] AL = 54H again
7
8 0000000C AC lodsb AL = 54H, but ESI = 000EH
9
10 0000000D 546861747320616E20- Msg db 'Thats an example'
11 00000016 6578616D706C65
What will probably be a lot of help to you is to study all the commonly used opcodes by tracing through a program you understand and watch what's happening through GDB, OLLYDBG etc.
Here's the exact same thing, with stuff moved around a little
1 [BITS 32]
2
3 00000000 A0[07000000] mov al, [Msg]
4 00000005 EB10 jmp Do
5
6 00000007 546861747320616E20- Msg db 'Thats an example'
7 00000010 6578616D706C65
8
9 Do:
10 00000017 BE[07000000] mov esi, Msg
11 0000001C 8A06 mov al, [esi]
12
13 0000001E AC lodsb
-
Is this what you're trying to do? (approximately)
; nasm -f elf isy.asm
; ld -o isy isy.o
global _start
section .data
string db "A user defined string" ; 21 bytes
string_size equ $ - string
section .text
_start:
nop
mov eax, [string]
mov [0x8049500], eax ; a "known" good address
mov eax, [string + 4]
mov [0x8049504], eax
mov eax, [string + 8]
mov [0x8049508], eax
mov eax, [string + 12]
mov [0x804950C], eax
mov eax, [string + 16]
mov [0x8049510], eax
mov al, [string + 20]
mov [0x8049514], al
; did it work?
mov edx, string_size
mov ecx, 0x8049500
mov ebx, 1
mov eax, 4
int 0x80
exit:
mov bl, 0
mov eax, 1
int 0x80
Best,
Frank
-
Thank you. It works perfect as always. :)