I'm calling a function from C that I define using NASM 2.13.3.1. I'm developing in Visual C++ Professional 2017 15.9.21.
Here is the C code:
#include <string.h>
extern _begin_asm_func(int, const char*, void*);
struct MyStruct
{
int64_t a;
int64_t b;
};
int main(int argc, char ** argv)
{
struct MyStruct x;
x.a = 1;
x.b = 2;
char str[] = "Hi";
int len = strlen(str);
_begin_asm_func(len, str, (void *)&x);
return 0;
}
NASM Code:
global _begin_asm_func
SECTION .data
SECTION .text
_begin_asm_func:
; align stack pointer to 16-byte boundary because return address (8 bytes) pushed by call \
PUSH rbx ;
PUSH r12 ;
PUSH r13 ;
PUSH r14 ;
PUSH r15 ;
; five pushes to save non-volitile registers for use later should also align stack
MOV r12, rcx ; store length in r12
MOV r13, rdx ; store string pointer in r13
MOV r14, r8 ; store pointer to data structure in r14
MOV r15, [r8] ; store first field value
; useful stuff will go here later...
POP r15 ;
POP r14 ;
POP r13 ;
POP r12 ;
POP rbx ;
RET ; access violation happens here
And here is the debugger output:
global _begin_asm_func
SECTION .data
SECTION .text
_begin_synergy_asm:
00007FF7E37718A0 push r12
00007FF7E37718A2 push r13
00007FF7E37718A4 push r14
00007FF7E37718A6 push r15
00007FF7E37718A8 mov r12, rcx
00007FF7E37718AB mov r13, rdx
00007FF7E37718AE mov r14, r8
00007FF7E37718B1 mov r15, qword ptr[r8]
00007FF7E37718B4 pop r15
00007FF7E37718B6 pop r14
00007FF7E37718B8 pop r13
00007FF7E37718BA pop r12
00007FF7E37718BC pop rbx
00007FF7E37718BD ret
The seg fault / access violation happens on return. Two things immediately jumped out at me. First, the first push
to rbx
is missing, and second, the address of the second push is on a 4-byte boundary. So it seems to me that the instructions are being mis-aligned by nasm, so the call is landing on the second instruction instead of the first. That mis-aligns the stack so that the number of pops don't match the mumber of pushes, so that ret
gets the wrong value for the return address.
Assuming alignment is the actual problem, how do I tell nasm to align the label for the function? I know the align directive is only for aligning data.
If that isn't the issue, then what is it and how can I avoid it?