0

I want to use interrupts in inline asm but it is not letting me I think my app is this

__asm__("movb %ah,9;" 
"movb %al,0x41;" 
"movb %bh,0x0;" 
"movw %cx,0x1; "
"movb %bl,0x0F ;" 
"int $10; ");

I am getting nothing after running this just a blank space what should I do?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
proh14
  • 21
  • 6
  • What are you trying to accomplish with this interrupt, and might it be accomplished without using one? – Scott Hunter May 06 '22 at 18:42
  • What are you running this in? DOS? Windows? Something else? The `int` instruction is really a system call. What do you expect this system call to do? What do you mean you get a blank space? Is there other output? How do you run the program? How do you know there is a blank space rather than just nothing? – Eric Postpischil May 06 '22 at 18:45
  • 1
    The first note is that it is interrupt `0x10`, not `10` (hex not decimal). But there are lots of other problems with this. You have AT&T syntax backwards; missing the `$` prefix on immediates; you don't have register clobbers; etc. Also, this looks like gcc, which normally generates code for 32- or 64-bit x86, but BIOS interrupts will only work in 16-bit real mode. Is this supposed to be an MS-DOS application, a bootloader, a bare-metal application, or what? How are you planning to compile and run this? – Nate Eldredge May 06 '22 at 18:45
  • 1
    Yes, I have some examples here https://stackoverflow.com/questions/43668314/reading-input-in-bios-level-assembly . Inline assembly is difficult to get right, even what seems very simple. Use inline assembly if you really understand it. There are some tutorials on Code Project that are terrible that are not very good (and buggy) resources combining inline assembly and 16-bit code. – Michael Petch May 06 '22 at 19:27
  • The assumption though is that this code is being written, compiled, and linked to be run in real mode with a legacy BIOS. It will not run properly in protected mode or long mode. – Michael Petch May 06 '22 at 19:36
  • @MichaelPetch: If it weren't for the fact that the FreeDOS team finally ported GCC and GAS to run targeting x86-16 I'd close this as definitely malformed due to attempting to assemble instructions for the wrong bitness. – Joshua May 06 '22 at 19:38
  • @Joshua : You can get this to work using `-m16` but it will only run in real mode on 386+ (since it uses 386 prefixes). The ia16-gcc project is still a work in progress and presents a number of troubling bugs (to this day). If it were me, I'd write such code with Watcom C and Watcom assembler (or one of its children). – Michael Petch May 06 '22 at 19:40
  • @MichaelPetch: The FreeDOS documents say otherwise. I'm pretty sure they're on a far branch of GCC. But they also have the watcom compiler which would be different syntax. (FreeDOS GCC itself is DPMI but does have a 16 bit 8086 output target.) – Joshua May 06 '22 at 19:42
  • @joshua See my other comment about ia16-gcc which Freedos may be using as well and it has its own problems if you don't know what they are. – Michael Petch May 06 '22 at 19:44
  • The code the OP has will assemble and link and run on a 386+ (not an 8086/80186/80286) with GCC (and the `-m16`) option in real mode. Even I don't recommend this, but it does work but in a constrained way (real mode and SS=DS=CS=ES=0) The advantage to ia16-gcc port is that it can target an 8086 and without all the 80386 address and data size prefixes smaller code as well (and is somewhat segment aware) – Michael Petch May 06 '22 at 20:13
  • Don't edit [solved] into the title. Instead, mark it as answered by clicking the checkmark under an answer. (You can write one yourself if the existing ones don't fully answer your question.) – Peter Cordes Aug 11 '22 at 16:11

1 Answers1

1

Can i use interrupts in inline assembly?

Yes, as long as the interrupt exists and you inform the compiler of how to deal with it correctly (e.g. "clobber list" to tell the compiler which registers changed, etc). See the GCC manual and https://stackoverflow.com/tags/inline-assembly/info

And as long as you use the correct number, likely you wanted int $0x10 instead of int $10. And you'll want to mov immediates into registers, not mov registers to absolute memory addresses.

If that doesn't work, I'd be tempted to suspect that you're trying to use BIOS "video services" to print a character on the screen; but you're not in real mode (and doing it in 32-bit code or 64-bit code); and the BIOS might not exist at all (e.g. a UEFI system); and an OS may have taken over control of the hardware (and broken all the assumptions that BIOS expects, like disabling obsolete "legacy junk emuation" in certain devices, reconfiguring memory, and timers and interrupt controllers; so that even if BIOS exists and you're in real mode you still can't use it safely).

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Brendan
  • 35,656
  • 2
  • 39
  • 66
  • Actually you can call video bios from protected mode. That's how VESA works. The OS detects the instruction is an int 10h instruction, transitions to the right cpu mode, lets it run, and transitions back. Although these days on x64 it just straight up emulates the x86-16 instead. But it won't run unless _you are the video driver_. Application code can't use it. – Joshua May 06 '22 at 19:40
  • @Joshua: So you're saying that (for an extremely restricted case on one unmentioned OS that is probably written by fools and can't be ported to ARM or UEFI without breaking video drivers) you still can't use `BIOS int 0x10` from protected mode and the OS needs emulate real mode (and a fake `int 0x10`)? – Brendan May 06 '22 at 19:49
  • No, I'm saying the VESA video driver on common OSes invokes int 10h. On x86, the VESA video driver is what you use until you install the correct video driver. I read the documentation on how the Linux driver works. (You would normally use a chipset driver. You use VESA when you jump the disk to new hardware until you can download the correct driver.) – Joshua May 06 '22 at 19:52
  • @Brendan: You also need to use the right interrupt number. `10` is decimal, `int $0xa`, not `int $0x10`. From a quick look, the code in the question is setting up args for `int 10h` / AH=9 write character with attributes. https://en.wikipedia.org/wiki/INT_10H, but then invoking `int 0Ah` – Peter Cordes May 06 '22 at 19:55
  • @PeterCordes: Yeah - I missed that earlier (not sure if typo or..). – Brendan May 06 '22 at 19:59
  • @Joshua: You're confirming what I said (hint: Linux is very much an OS written by fools). For a sane OS the boot loader sets up a default video mode and frame buffer; then the frame buffer is used until/unless a real video driver is installed; and this is what happens for Linux in most cases. – Brendan May 06 '22 at 20:05
  • @Brendan: That would be nice, but on x86, the framebuffer from the boot loader is still in text mode unless the boot loader has a video driver, in which case jump disk still doesn't work and you're back in text mode anyway. – Joshua May 06 '22 at 20:10
  • @Joshua: Yes? That's how Linux was designed. The kernel just used text mode frame buffer and didn't have any video driver at all for about 10 years (until people got annoyed at how stupid it is, ignored the principles of "monolithic kernel" and hacked video drivers into user-space). Eventually (after being bumbling fools for about 20 years) they introduced "kernel mode setting" and boot loaders (e.g. GRUB) became able to set up a graphics mode before starting the kernel. – Brendan May 06 '22 at 20:14
  • Ah, but KMS doesn't work on quite a bit of video cards. The VESA driver actually got good enough to start X and launch a graphical web browser so you can use the web to track down the correct driver. (Don't get started on text mode web browsers. There's a different set of fools who broke them.) – Joshua May 06 '22 at 20:18
  • I also remember when KMS first came out and the kernel was autodetecting the *wrong* driver for my video card and DMA corrupting RAM because of it. I had to boot emergency kernel (the kernel from before the upgrade) and track down and blacklist the KMS driver. – Joshua May 06 '22 at 20:20
  • @Joshua: Sure - plenty of hacky nonsense everywhere for various cases. Even if VESA can work, it doesn't really work well (e.g. plenty of video card ROMs that only offer a limited number of lower resolution modes where none match the monitor's native resolution). – Brendan May 06 '22 at 20:22
  • @Brendan I corrected my code _asm__("movb $9,%ah;" "movb 'A',%al;" "movb $0,%bh;" "movw $50,%cx; " "movb $0x0F0,%bl ;" "int $0x10; "); I first tried to run it in windows but again blank space :( after this, I ran it in Linux and the terminal gave me an error "Segmentation fault" – proh14 May 07 '22 at 10:53
  • @proh14: yeah. Firmware (BIOS, UEFI, OpenFirmware, Uboot maybe, ...) primarily exists so that an OS can "pull itself up by its bootstraps" (boot). When an OS boots it obliterates all the firmware's junk, starts its own drivers, and provides its own interfaces (and then buries its own low level interfaces under other abstractions, like a C library or GUI library). You'd have more luck getting BIOS to work if there's no OS installed at all. – Brendan May 07 '22 at 11:04
  • @proh14: If you're intent on making this work, try DosBox. – Joshua May 07 '22 at 14:54
  • @Joshua I actually developed dos with dos.h (REGS and int86 function)but I need to make this work in windows – proh14 May 07 '22 at 16:07
  • @proh14: It won't. Windows doesn't send `int 10h` anywhere useful. – Joshua May 07 '22 at 16:31
  • remembrance of old dos days – proh14 May 08 '22 at 10:50