I want to combine c and assembly code.
I have the following C code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern void _increment(unsigned short *x);
int main(int argc, char** argv)
{
unsigned short x = 0;
_increment(&x);
printf("%d", x)
return 0;
}
and the assembly(32bit NASM) code:
section .text
global _increment
_increment:
push ebx
mov bx, word [esp 8] ;what is stored in bx here? the x address?
mov ax, [bx] ;what is stored in ax here? the x value?
;add word [esp 8], 1 -> dosnt work
pop ebx
ret
section .data
if I execute this I get an Segmentation fault. Can someone explain what is stored in the registers/stack? and maybe how I can increment the Value and not the address of X?
CodePudding user response:
It's clear you understand how pointers work in general, the only mistake was the size of the pointer itself. On nearly all CPUs, the size of a pointer (not the size of the thing it points to) is going to equal the size of the instruction pointer register (often called PC for program counter on non-x86 architectures.) There are exceptions to this rule, but usually it's just going to match your hardware's default register size. Which is why, as you mentioned in the comments, that you only loaded half the pointer because you used bx
as the destination of your load from the stack. In x86, the register operand that's not in brackets determines the number of bytes that will be read/written to memory. This is why you don't get an assembler error for mismatched operand size when you execute mov bx, word [esp 8]
even though esp
is 32-bit and bx
is 16-bit; the right operand is 16-bit memory rather than a 32-bit register.