24

I have a (very) basic understanding of assembly using system calls on Linux (I use the GNU assembler as). On Windows 7, I am using the MinGW (32-bit) port of the GCC compiler suite to produce assembler programs. On Linux I regularily use the C library for some OS interactions in my assembler programs, and on my Windows platform this works perfectly as well using MinGW. Sometimes, however, I want to use low-level system calls -- mostly to keep my executables as small as possible. On Linux I know how to do this:

movl        $0, %ebx
movl        $1, %eax
int $0x80   ; exit with code 0

I also use these system calls for reading/writing chars to/from the terminal (for writing syscall with 4 in EAX for example). I was wondering how to do this on a Windows NT platform. Is it possible? I looked at this table, but I don't really understand the names of the syscalls. Any help is welcome.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
DiscobarMolokai
  • 544
  • 2
  • 6
  • 20
  • 4
    Inlining system calls instead of `call`ing a library wrapper function doesn't usually save much code size, especially if you're missing [well-known optimizations like `xor %ebx,%ebx`](https://stackoverflow.com/questions/33666617/what-is-the-best-way-to-set-a-register-to-zero-in-x86-assembly) instead of `mov $0, %ebx`. Also, `int 0x80` on Linux is the slow legacy way to invoke the 32-bit ABI. The recommended way is to call into the VDSO so it can use `sysenter` for better performance. https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/ – Peter Cordes Mar 25 '18 at 13:49
  • 2
    and you can get 0 and 1 into 2 registers in 6 bytes instead of 10 bytes like that with [`xor ebx, ebx; lea eax, [ebx + 1]`](https://stackoverflow.com/a/49799878/995714). or `xor eax, eax; cdq; inc edx` which costs only 4 bytes (5 in x86_64) – phuclv Aug 08 '18 at 15:00

1 Answers1

22

The Nt* set of functions are undocumented with good reason: it's internal to Windows and changes between versions, meaning that programs that target it directly are at high-risk of breaking between Windows versions.

Really, there is not that big an overhead with targeting public, documented functions, and you get Microsoft's guarantee that your program will work with future versions of Windows provided you use the API correctly.

For that reason, I won't provide you with the answer you want. I strongly advise you to use the public console API: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073%28v=vs.85%29.aspx

Update

I assume that is for experimentation or fun, indeed the OP wrote:

Sometimes, however, I want to use low-level system calls -- mostly to keep my executables as small as possible.

...I find this line of reasoning problematic and I don't want to act as an enabler for these kinds of development practices, especially as there is no practical benefit to using syscalls for console tasks.

If someone wants to know how to use low-level syscalls in Windows then please post a new question, suitably framed, and I'll gladly answer it.

But as a starting point, see https://j00ru.vexillium.org/syscalls/nt/64/ for a reverse-engineered table of x64 NT system-call numbers broken down by Windows kernel version. (Do not use in portable code, only for experiments to satisfy your curiosity about how Windows and/or asm works.)

E_net4
  • 27,810
  • 13
  • 101
  • 139
Dai
  • 141,631
  • 28
  • 261
  • 374
  • 5
    I was just playing around with assembly code, that's all -- portability isn't important to me for these small experiments ;) But thanks, your advice is very useful I'll certainly take note +1 **EDIT:** I assume using the C library with the MinGW port of as I'm using is a valid alternative for the public console API? – DiscobarMolokai Jan 12 '14 at 12:27
  • @DiscobarMolokai: last time I checked, MinGW GCC used Microsoft's C library, `msvcrt.dll`. Strictly speaking, using that library this way isn't supported (that I know of) but it's a widespread practice. It should certainly be good enough for your scenario. – Harry Johnston Jan 12 '14 at 19:57
  • @HarryJohnston @DiscobarMolokai the CRT console functions (e.g. `prinf`, `gets`, etc) call-into the Win32 console functions, making them synonymous. – Dai Jan 13 '14 at 01:45
  • 14
    -1, many people who play around with internals just do it for fun/research/learning, not because they plan to develop releasable piece of software. – Hayley Feb 16 '15 at 00:07
  • 3
    I should stress that this was definitely the answer I needed back when I posted my question, even though it was just hacking around for fun, and I support Dai's position about the matter. My question certainly could have been clearer—I was a newbie around here in '14 and didn't appreciate the value of being concise and to the point in questions—so perhaps the question could be edited to reflect this more clearly? People still seem to stumble across this question every now and then, and I can see how the current state of affairs could cause confusion. – DiscobarMolokai Mar 29 '17 at 06:55
  • 1
    @DiscobarMolokai: I think the current question is fine, especially with Dai's recent edit to the answer. It would be great if either the question or answer had a link to how to something about making Windows kernel system calls directly (with x86-64 `syscall` or whatever they do in 32-bit mode), after suitable warning labels that it won't be portable. – Peter Cordes Mar 25 '18 at 13:53
  • @PeterCordes No need: there's enough good info in the linked QA: https://stackoverflow.com/questions/2489889/system-calls-in-windows-native-api – Dai Apr 14 '23 at 05:32
  • There is now, after I edited an answer there in 2019, around the same time I added the https://j00ru.vexillium.org/syscalls/nt/64/ link to this answer. Neither answer was as good in May 2018. (When I closed this question as a duplicate of it, 2 days before that comment you're replying to, according to the timestamps. I probably hadn't found j00ru's page at that point.) – Peter Cordes Apr 14 '23 at 05:44
  • 1
    @PeterCordes Well, in any event I'm just surprised that my non-answer, where I basically shoot-down the OP, got upvoted so much, lol – Dai Apr 14 '23 at 06:46
  • IIRC, it's one that I've used as a canonical duplicate as questions about using system calls on Windows keep getting asked. (Or more often, people with code from a Linux tutorial they don't understand, trying + failing to build it into a Windows executable, which wouldn't run correctly if they did get it to assemble + link.) Or at least a link in comments. This question's list of linked questions is fairly long. Also, in its current state it *does* have some info about the low level details, and a useful link. I upvoted it a while ago (perhaps after I edited it :P). – Peter Cordes Apr 14 '23 at 06:48