Author Topic: Interfacing NASM with g++ and VC++ 2017  (Read 533 times)

Offline kanito73

  • Jr. Member
  • *
  • Posts: 10
Interfacing NASM with g++ and VC++ 2017
« on: February 15, 2019, 04:42:29 AM »
Hello friends

Today is the time to interface NASM with C++ using g++ and VC++ (2017). Do you know of a tutorial that I can use?

The examples in the manual demostrate how to call assembly functions and how to pass numerical arguments, but in particular I need to pass pointers to strings and data buffers from C++ to ASM. And also require to see how to link the object file in Windows using VC++, for Linux it already shows how to do it.

In advance, thanks for your help and comments

Offline sonictk

  • Jr. Member
  • *
  • Posts: 5
Re: Interfacing NASM with g++ and VC++ 2017
« Reply #1 on: February 15, 2019, 06:11:12 PM »
Hi there:

I _just_ wrote a tutorial about working with x64 assembly on Windows that covers this topic:

https://sonictk.github.io/asm_tutorial/

You can skip to the "Using assembly in C/C++ programs" section, or take a look at the code samples and build scripts in the accompanying code repository for the tutorial.

Hope this helps!

Offline kanito73

  • Jr. Member
  • *
  • Posts: 10
Re: Interfacing NASM with g++ and VC++ 2017
« Reply #2 on: February 15, 2019, 06:31:52 PM »
Hi !!!

Thanks for your response. I just opened the link and the tutorial appears to be pretty complete. I think it will be a good idea to read it entirely.

Thanks!!!

Offline sonictk

  • Jr. Member
  • *
  • Posts: 5
Re: Interfacing NASM with g++ and VC++ 2017
« Reply #3 on: February 15, 2019, 10:44:35 PM »
Hi !!!

Thanks for your response. I just opened the link and the tutorial appears to be pretty complete. I think it will be a good idea to read it entirely.

Thanks!!!

No problem. Feel free to post a comment on the blog or ping me on Twitter if something doesn't make sense!

Offline kanito73

  • Jr. Member
  • *
  • Posts: 10
Re: Interfacing NASM with g++ and VC++ 2017
« Reply #4 on: February 16, 2019, 04:07:03 AM »
Hi !!!

Thanks for your response. I just opened the link and the tutorial appears to be pretty complete. I think it will be a good idea to read it entirely.

Thanks!!!

No problem. Feel free to post a comment on the blog or ping me on Twitter if something doesn't make sense!


Hello

I'm still reading your tutorial, it is very complete and illustrative, congratulations! Finally reached the "The Microsoft x64 Calling Convention" and I have two doubts.

1. If I pass a pointer from C++ to ASM, is it considered an INTEGER VALUE and it is passed into the registers RCX/RDX/R8/R9 (or the stack if necessary) as a normal number? And if so, is it only the OFFSET and the current DATA SEGMENT is assumed to contain the data?

2. If I need to pass different size arguments (byte, word, dword, qword), are they passed as full 64-bits values and just have to extract the required size, for example CL, CX, ECX or RCX according to the parameter size in C++? And, I suposse that no matter if it is a signed or unsigned value, the assembly function processes the value in the required way depending on the expected data size, let be an unsigned integer or a signed integer (maybe in two's complement if highest bit is set)?

Regards,
and again, congratulations for your tutorial!

Offline fredericopissarra

  • Jr. Member
  • *
  • Posts: 49
Re: Interfacing NASM with g++ and VC++ 2017
« Reply #5 on: February 16, 2019, 10:46:53 AM »
Hello...

1. If I pass a pointer from C++ to ASM, is it considered an INTEGER VALUE and it is passed into the registers RCX/RDX/R8/R9 (or the stack if necessary) as a normal number? And if so, is it only the OFFSET and the current DATA SEGMENT is assumed to contain the data?

Pointers are normal integer values and these integer values are used as memory addresses. Their sizes depends on the architecture.

In x86-64 mode all addresses are 64 bits in size (but only 48 bits are used - 52 if PSE is enabled for a page). The remaining bits must be a copy of the last valid bit (this is called "cannonical addressing" - take a look at topic 3.3.7 on Intel's "Software Development Manual, vol 1"). For exemple, this address is cannonical: 0x7fffffffffff; but this is not: 0x800000000000, because only bits 0~47 are valid and in the later case bit 48=1. The cannonical address here is 0xffff800000000000).

It is useful to know abour cannonical addressing, but with 48 bits it's possible to address 256 TiB of memory!!! And with 52 bits, 2 PiB!!! Without worrying about cannonization! :)

Also, in x86-64 mode no selector registers are used, except CS (only to hold the Current Privilege Level), FS and GS. The memory is always flat regarding segmentation. The protection is enforced by the paging mechanism. Take a look at any simple program with GDB and you'll see something like this:

Code: [Select]
(gdb) l
1   bits 64
2   default rel
3
4   global _start
5 _start:
6   xor   edi,edi
7   mov   eax,60
8   syscall
(gdb) b 6
Breakpoint 1 at 0x400080: file test.asm, line 6.
(gdb) r
Starting program: /mnt/vol2/Work/tmp/test

Breakpoint 1, 0x0000000000400080 in _start ()
(gdb) info registers
rax            0x0 0
rbx            0x0 0
rcx            0x0 0
rdx            0x0 0
rsi            0x0 0
rdi            0x0 0
rbp            0x0 0x0
rsp            0x7fffffffdcf0 0x7fffffffdcf0
r8             0x0 0
r9             0x0 0
r10            0x0 0
r11            0x0 0
r12            0x0 0
r13            0x0 0
r14            0x0 0
r15            0x0 0
rip            0x400080 0x400080 <_start>
eflags         0x202 [ IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0 0
es             0x0 0
fs             0x0 0
gs             0x0 0

See that DS-ES are all zero? CS and SS holds information used by the kernel, but the processor will ignore everything, except the RPL field of CS.

2. If I need to pass different size arguments (byte, word, dword, qword), are they passed as full 64-bits values and just have to extract the required size, for example CL, CX, ECX or RCX according to the parameter size in C++? And, I suposse that no matter if it is a signed or unsigned value, the assembly function processes the value in the required way depending on the expected data size, let be an unsigned integer or a signed integer (maybe in two's complement if highest bit is set)?

Yes, but you don't need to initialize all 64 bits. For instance:
Code: [Select]
int f(int x) { return x+x; }
...
y=f(10);

Creates code like this:

Code: [Select]
f:
  ; The compiler uses RDI here to avoid insering an extra prefix
  ; to the instruction (0x67). Otherwise, the instruction could be
  ; lea eax,[edi+edi].
  lea   eax,[rdi+rdi]
  ret
...
mov edi,10    ; EDI, not RDI!
call f
...

For byte sized arguments there are aliases to RDI and RSI: DIL and SIL.

If an integer is interpreted as signed or unsigned is a matter of using the flags. All integer arithmetic is done if the data is unsigned and sets CF and OF accordingly.

[]s
Fred
« Last Edit: February 16, 2019, 11:01:14 AM by fredericopissarra »

Offline kanito73

  • Jr. Member
  • *
  • Posts: 10
Re: Interfacing NASM with g++ and VC++ 2017
« Reply #6 on: February 16, 2019, 06:13:20 PM »
Thanks a lot for your time and patience to write!

Now everything is clear as water... I will test on code to finally develop my library functions.

Have a nice day!  =-)