2

Just wondering, in regards to my post Alternatives to built-in Macros, is it possible to avoid using the StdOut macro by using the int 21h windows API? Such as:

.data
       msg dd 'This will be displayed'
;original macro usage:
invoke StdOut, addr msg
;what I want to know will work
push msg 
int 21h ; If this does what I think it does, it should print msg

Does such a thing exist (as in using int 21h to print things), or does something like it exist, but not exactly int 21h. Or am I completely wrong.

Could someone clarify this for me?

Thanks,

Progrmr

rkhb
  • 14,159
  • 7
  • 32
  • 60
Progrmr
  • 1,575
  • 4
  • 26
  • 44

3 Answers3

8

The interrupt 21h was the entry point for MS-DOS functions.

For example to print something on stdout you have to:

mov ah, 09h  ; Required ms-dos function
mov dx, msg  ; Address of the text to print
int 21h      ; Call the MS-DOS API entry-point

The string must be terminated with the '$' character.

But:

  • You cannot use interrupts in Windows desktop application (they're available only for device drivers).
  • You must write a 16 bit application if you need to call MS-DOS functions.

Then...yes, you can't use it to print messages, nothing like that exists: you have to call OS functions to print your messages and they are not available via interrupts.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • You _can_ use interrupts in a desktop application (just not the DOS ones). See my answer for details. And yes, you can print messages using the system calls, you just have to be specific which version of Windows you target. – Ruslan Apr 17 '18 at 10:47
  • @Ruslan yes, _some_ interrupts are available (3h for debugger breakpoint the one that came to my mind) and I wouldn't use 2eh but hey, it's an interesting info! I never thought there is anything else but `sysenter`/`syscall`!!! (naively I was under the impression a _normal_ `call` and some _magic_ were enough even on very old processors). – Adriano Repetti Apr 17 '18 at 11:43
  • A device driver might set up an interrupt *handler*, but if you're already running in the kernel you wouldn't use an `int xx` instruction; you'd just use `call` to run other kernel code. (I don't do Windows development but it would be very unusual for a kernel to trigger a software interrupt.) – Peter Cordes Oct 25 '19 at 12:21
  • @PeterCordes I actually don't know if _they_ do it or not but I can imagine a couple of (highly) hypothetical reasons (with `call` you might need to save the whole thread state by yourself; you might want to _artificially_ call it inside an higher IRQL; you may want to call it if not masked) – Adriano Repetti Oct 25 '19 at 13:16
2

DOS interrupts cannot be used in protected mode on Windows.

You can use the WriteFile Win32 API function to write to the console, or use the MASM macro instead.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
blez
  • 4,939
  • 5
  • 50
  • 82
  • 1
    You meant virtual-8086 mode, which is a sub-mode of protected mode (in which the whole OS runs anyway). Also, virtual-8086 is not available in 64-bit mode anymore. – Daniel Kamil Kozar May 14 '12 at 14:36
  • Thanks. Do I do `call WriteFile` after pushing parameters to the stack? And is there also such thing as `_WriteConsole`? – Progrmr May 15 '12 at 03:29
  • 1
    All console outputs use `WriteFile`. Look here: http://www.nymtec.com/assembly-console-hello-world in hw.asm, also you can replace the edx parameter with 7 (as far as I remember) and it will still work). With pushes you just push from right to left order, and then: call WriteFile – blez May 15 '12 at 11:50
  • And for clarification, on another website, I have seen a command called `extern`. Is this how I link to the Windows API's? – Progrmr May 16 '12 at 01:21
  • I haven't used MASM for a long time (I use FASM instead), but I think extern was for showing what functions you want to use from the .lib (But I'm not sure). Google it. – blez May 16 '12 at 14:55
2

The other answers saying that you cannot use interrupts in Windows are quite wrong. If you really want, you can (that's not recommended). At least on 32-bit x86 Windows there's the legacy int 2Eh-based interface for system calls. See e.g. this page for a bit of discussion of system call mechanisms on x86 and x86_64 Windows.

Here's a very simple example (compiled with FASM) of a program, which immediately exits on Windows 7 using int 0x2e (and crashes on most other versions):

format PE
NtTerminateProcess_Wind7=0x172
entry $
    ; First call terminates all threads except caller thread, see for details:
    ; http://www.rohitab.com/discuss/topic/41523-windows-process-termination/
    mov eax, NtTerminateProcess_Wind7
    mov edx, terminateParams
    int 0x2e
    ; Second call terminates current process
    mov eax, NtTerminateProcess_Wind7
    mov edx, terminateParams
    int 0x2e
    ud2    ; crash if we failed to terminate
terminateParams:
    dd 0, 0 ; processHandle, exitStatus

Do note though, that this is an unsupported way of using Windows: the system call numbers are changing quite often and in general can't be relied on. On this page you can see that e.g. NtCreateFile on Windows XP calls system call number 0x25, while already on Windows Server 2003 this number corresponds to NtCreateEvent, and on Vista it's NtAlpcRevokeSecurityContext.

The supported (albeit not much documented) way of doing the system calls is through the functions of the Native API library, ntdll.dll.

But even if you use the Native API, "printing things" is still very version-dependent. Namely, if you have a redirect to file, you must use NtWriteFile, but when writing to a true console window, you have to use LPC, where the target process depends on Windows version.

Ruslan
  • 18,162
  • 8
  • 67
  • 136
  • 2
    Ok, but you can't use *DOS* `int 21h` in 32-bit protected mode, can you? Obviously that's what they meant. Upvoted for the interesting notes on the ntdll <-> kernel ABI, though. – Peter Cordes Apr 17 '18 at 10:07