The problem is that the syntax is adapted for Linux usage, and poorly documented.
Resulting code (which seem to be correct):
Code: Select all
00000180e00000b0 <main>:
180e00000b0: 41 56 push %r14
180e00000b2: 48 8d 3d ff 01 00 00 lea 0x1ff(%rip),%rdi # ffffffffe00002b8 <_end+0xfffffe7ebffff900>
180e00000b9: 41 be 7b 00 00 00 mov $0x7b,%r14d
180e00000bf: 45 31 c0 xor %r8d,%r8d
180e00000c2: 41 54 push %r12
180e00000c4: 41 bc 09 00 00 00 mov $0x9,%r12d
180e00000ca: 53 push %rbx
180e00000cb: 0f 05 syscall
180e00000cd: 72 06 jb 180e00000d5 <main+0x25>
180e00000cf: 48 0f b7 c3 movzwq %bx,%rax
180e00000d3: eb 03 jmp 180e00000d8 <main+0x28>
180e00000d5: 48 31 c0 xor %rax,%rax
180e00000d8: 41 89 c2 mov %eax,%r10d
180e00000db: 85 c0 test %eax,%eax
180e00000dd: 74 2a je 180e0000109 <main+0x59>
180e00000df: 41 be 86 00 00 00 mov $0x86,%r14d
180e00000e5: 48 8b 3d 1c ff ff 3f mov 0x3fffff1c(%rip),%rdi # 20000008 <usergate_entries+0x1ffffeb4>
180e00000ec: 41 b8 f4 01 00 00 mov $0x1f4,%r8d
180e00000f2: 66 41 bc f4 01 mov $0x1f4,%r12w
180e00000f7: 0f 05 syscall
180e00000f9: 73 03 jae 180e00000fe <main+0x4e>
180e00000fb: 48 31 c0 xor %rax,%rax
180e00000fe: 41 be 7d 00 00 00 mov $0x7d,%r14d
180e0000104: 44 89 d3 mov %r10d,%ebx
180e0000107: 0f 05 syscall
180e0000109: 5b pop %rbx
180e000010a: 41 5c pop %r12
180e000010c: 31 c0 xor %eax,%eax
180e000010e: 41 5e pop %r14
180e0000110: c3 retq
Source:
Code: Select all
#define RdosClobberSyscall \
asm volatile ( \
"\n\t" \
: : : "rcx", "r9", "r11", "r14" \
);
#define RdosClobberSyscallRdi \
asm volatile ( \
"\n\t" \
: : : "rcx", "rdi", "r9", "r11", "r14" \
);
#define RdosUserGateEdiEcxPar0RetEbx(nr, rdi, rcx, size, res) do { \
register int _id asm("r14") = nr; \
register typeof(rdi) _rdi asm("rdi") = (rdi); \
register typeof(rcx) _rcx asm("r8") = (rcx); \
register typeof(size) _size asm("r12") = (size); \
asm volatile ( \
"syscall\n\t" \
"jc 1f\n\t" \
"movzx %%bx,%%rax\n\t" \
"jmp 2f\n\t" \
"1: \n\t" \
"xorq %%rax,%%rax\n\t" \
"2: \n\t" \
: "=a" (res) : "r" (_id), "r" (_rdi), "r" (_rcx), "r" (_size) : "rbx", "rdx", "rsi" \
); \
RdosClobberSyscallRdi; \
} while(0);
#define RdosUserGateEbxEdiEcxParRetEax(nr, rbx, rdi, rcx, res) do { \
register int _id asm("r14") = nr; \
register typeof(rdi) _rdi asm("rdi") = (rdi); \
register typeof(rcx) _rcx asm("r8") = (rcx); \
register typeof(rcx) _size asm("r12") = (rcx); \
asm volatile ( \
"syscall\n\t" \
"jnc 1f\n\t" \
"xorq %%rax,%%rax\n\t" \
"1: \n\t" \
: "=a" (res) : "r" (_id), "r" (_rdi), "r" (_rcx), "r" (_size) : "rdx", "rsi" \
); \
RdosClobberSyscallRdi; \
} while(0);
#define RdosUserGateEbx(nr, rbx) do { \
register int _id asm("r14") = nr; \
register typeof(rbx) _rbx asm("rbx") = (rbx); \
asm volatile ( \
"syscall\n\t" \
: : "r" (_id), "r" (_rbx) : "rax", "rdx", "rsi", "rdi" \
); \
RdosClobberSyscall; \
} while(0);
RDOSAPI int RdosOpenFile(const char *FileName, char Access)
{
int res;
int size = strlen(FileName) + 1;
RdosUserGateEdiEcxPar0RetEbx(usergate_open_file, FileName, Access, size, res);
return res;
}
RDOSAPI int RdosReadFile(int Handle, void *Buf, int Size)
{
int res;
RdosUserGateEbxEdiEcxParRetEax(usergate_read_file, Handle, Buf, Size, res);
return res;
}
RDOSAPI RdosCloseFile(int Handle)
{
RdosUserGateEbx(usergate_close_file, Handle);
}
I'm not sure about the typeof definitions. A better idea is probably to define these as "int" instead. The assembler code has one of the loads in a word format, which would be wrong by itself (but is correct since the higher half is cleared before in the code).