In 32-bit programming i could push the offset of a variable onto stack the following way:
.data
variable byte ?
.....

.code
.....
push offset variable


When i try to do that with 64-bit programming it doesn't let me do that.
I wonder if there is a special instruction for that in 64-bit programming.

I am using MASM (ml64.exe). So maybe i am wondering if it has to do with the assembler.

Edit: Nevermind, i found out that it was a bug in MASM. I am switching assemblers. I am trying 64-bit hello world in NASM but it crashes. The same code in MASM64 works. I wonder what i am doing wrong.

global _main

extern GetStdHandle
extern WriteFile
extern ExitProcess

section .text
_main:
mov rcx, -11
call GetStdHandle

mov rcx, rax
mov rdx, message
mov r8, (message_end - message)
mov r9, BytesWritten
mov qword , 0
call WriteFile

mov rcx, 0
call ExitProcess

;variables
BytesWritten: dq 0
message: db "Hello World"
message_end:

nasm -fwin64 main.asm <-assembles successfully
link /subsystem:console /entry:_main /machine:x64 main.obj kernel64.lib <- links successfully
main <- crashes
Posted on 2011-01-31 18:58:27 by banzemanga
Is your stack aligned? Check out GoAsm's Manual for a fairly detailed explanation on how to use 64-bit FASTCALL.
Posted on 2011-02-01 10:38:55 by SpooK
I found that stack alignment was not the issue. I checked NASM manual and it said that NASM doesn't remember the addresses of variables unlike MASM. So, i could not do this:
mov		r9, BytesWritten


I found a crazy working solution somewhere else but i don't understand it:

_main:
;at the beginning of the code
mov rbp, rsp ;So, it first sets the base-pointer as the stack-pointer. (why? and not even saving rbp first?)
add rsp, 8 ;Decreases the size of the stack. (again why? what if there was something on the stack beforehand?)
...
...
;replace {mov r9, BytesWritten} with:
mov r9, ;Uses the empty space on top of the stack
...
Posted on 2011-02-01 11:29:17 by banzemanga
Ok, i found the reason why it was not working. The reason is because i had everything on a code segment (section .text).
NASM does actually allow to pass addresses of a labe in the code segment. What my original problem used to cause is that i had variables on the code section and Windows does not allow to modify anything on the code section making it crash.

So the right solution was to create a separate data segment (section .data) and puts the variables there.
global _main

extern GetStdHandle
extern WriteFile
extern ExitProcess

section .data
BytesWritten: dq 0
message: db "Hello World!"
message_end:

section .text
_main:
mov rcx, -11
call GetStdHandle

mov rcx, rax
mov rdx, message
mov r8, (message_end - message)
mov r9, BytesWritten
mov qword , 0
call WriteFile

mov rcx, 0
call ExitProcess


As for the weird solution i found, what i believe it was trying to do was to create local variables and the correct way to do it would be:
push		rbp
mov rbp, rsp
sub rsp, 8*1 ;8*1 because only one variable of 8 bytes
Posted on 2011-02-01 12:24:34 by banzemanga

I checked NASM manual and it said that NASM doesn't remember the addresses of variables unlike MASM.


NASM wouldn't be much of an assembler if it didn't. Variable references = labels = addresses.

What you are referring to is the fact that NASM doesn't keep/assume the type or value related to a variable/label.
Posted on 2011-02-01 18:34:06 by SpooK

What you are referring to is the fact that NASM doesn't keep/assume the type or value related to a variable/label.

I can't no longer find what NASM's manual originally said. You are right on the part that i was wrong about the label addresses. But i don't think its what you are mentioning neither because i don't think that MASM will assume a type or value on labels neither.

Edit: I found it and you were right. Well, reading it directly literally is rather confusing.
Rather than "remembering the variable type" is more like "storing the data size" of the variable for when passing a value back onto the memory.

Thanks.
Posted on 2011-02-01 20:01:07 by banzemanga
Yes, as data types have an implicit/defined size, which is the primary consideration with regard to assembly language.
Posted on 2011-02-01 22:10:48 by SpooK

Ok, i found the reason why it was not working. The reason is because i had everything on a code segment (section .text).
NASM does actually allow to pass addresses of a labe in the code segment. What my original problem used to cause is that i had variables on the code section and Windows does not allow to modify anything on the code section making it crash.


That is correct.
By default, the .text section is read-only. You could use some linker options to make it read-write, and use it as a data section. But under normal circumstances it's better to just use a .data section.
Posted on 2011-02-02 03:54:50 by Scali