I've been looking around a lot for examples of using inline ASM and I've seen seen a few different approaches.
I've gone with the -masm=intel option when compiling. As I understand it, when using this option you can just write the inline ASM as you would with intel syntax.
I have also seen approaches where people use ".intel_syntax"
When I compile I get the following message.
i586-mingw32msvc-gcc -masm=intel -o KDOS.exe KDOS.c
/tmp/ccVIXhRF.o:KDOS.c:(.text+0x5f): undefined reference to `address'
/tmp/ccVIXhRF.o:KDOS.c:(.text+0x6a): undefined reference to `ipAddr'
/tmp/ccVIXhRF.o:KDOS.c:(.text+0x79): undefined reference to `csAddr'
/tmp/ccVIXhRF.o:KDOS.c:(.text+0x11d): undefined reference to `address'
collect2: ld returned 1 exit status
I've looked around for a solution but I can't seem to find one. I've seen threads saying you can't pass C variables into inline ASM, but I've also seen some stuff saying there are workarounds. They didn't quite apply to what I was doing though so I wasn't really sure what to make of them. Sorry if it is an obvious answer but this is my first time using inline ASM much less fooling around with converting the syntax.
Here is my code. I am working through a book and this is some sample code within it. It was not compiled with gcc in the book so this is why I need to convert to intel syntax, because I need it to run on windows obviously. This is my modified version of the code:
// KDOS.c
// Chapter 2
#include<stdio.h>
#define WORD unsigned short
#define IDT_001_ADDR 0 //start address of first IVT vector
#define IDT_255_ADDR 1020 //start address of last IVT vector
#define IDT_VECTOR_SZ 4 //size of each IVT Vector (in bytes)
#define BP __asm{ int 0x3 } //break point
void main()
{
WORD csAddr; //Code segment of given interrupt
WORD ipAddr; //Starting IP for given interrupt
short address; //address in memory (0-1020)
WORD vector; //IVT entry ID (i.e., 0..255)
char dummy; //strictly to help pause program execution
vector = 0x0;
printf("\n---Dumping IVT from bottom up---\n");
printf("Vector\tAddress\t\n");
for
(
address=IDT_001_ADDR;
address<=IDT_255_ADDR;
address=address+IDT_VECTOR_SZ,vector++
)
{
printf("%03d\t%08p\t",vector,address);
//IVT starts at bottom of memory, so CS is alway 0x0
__asm__
(
".intel_syntax;"
"PUSH ES;"
"MOV AX, 0;"
"MOV ES,AX;"
"MOV BX,address;"
"MOV AX,ES:[BX];"
"MOV ipAddr,AX;"
"INC BX;"
"INC BX;"
"MOV AX,ES:[BX];"
"MOV csAddr,AX;"
"POP ES;"
);
printf("[CS:IP]=[%04X,%04X]\n",csAddr,ipAddr);
}
printf("press [ENTER] key to continue:");
scanf("%c",&dummy);
printf("\n---Overwrite IVT from top down---\n");
/*
Program will die somwhere around 0x4*
Note: can get same results via DOS debug.exe -e command
*/
for
(
address=IDT_255_ADDR;
address>=IDT_001_ADDR;
address=address-IDT_VECTOR_SZ,vector--
)
{
printf("Nulling %03d\t%08p\n",vector,address);
__asm__
(
".intel_syntax;"
"PUSH ES;"
"MOV AX,0;"
"MOV ES,AX;"
"MOV BX,address;"
"MOV ES:[BX],AX;"
"INC BX;"
"INC BX;"
"MOV ES:[BX],AX;"
"POP ES;"
);
}
return;
}/*end main()------------------------------------------------------------*/
Any help would be greatly appreciated. Once again my apologies if it is something obvious.
Actually you can pass C
arguments to inline asm
. But You have to define it after the asm code part.
In Your case something like this could work (You should add -masm=intel
to the gcc
's command line):
asm(
".intel_syntax noprefix;\n\t"
...
"MOV BX,%[address];\n\t"
...
".intel_syntax prefix;\n\t"
:: [address] "m" address, ...
: "AX", "BX", /* all changed registers to inform compiler to save them if needed */
);
See examples in a similar question.