0

I cannot find an answer for this on SO so far, so here I am asking. I'm wanting to find a macOS equivalent for the interrupt system call 10h; i.e. converting this:

mov ah, 2
mov bh, 1
mov dh, 12
mov dl, 40
int 10h

Into something that won't segfault on a NASM compiled macOS 64-bit program.

I've been scouring this document: https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master but sys call 17 isn't the same as the linux one apparently, and I'm not sure what to search for outside of this (very new to asm).

This is what I've got so far;

    mov dh, 5           ;Cursor position line
    mov dl, 0           ;Cursor position column
    mov ah, 0x02         ;Set cursor position function
    mov bh, 0           ;Page number
    mov rax, 0x02000000
    add rax, 0x10
    mov rdi, 1
    syscall             ;Interrupt call

So I was wondering; just how can I make the cursor move to the desired coordinates on macOS asm?

Jenna
  • 97
  • 7
  • 1
    `int 10h` is a legacy PC BIOS call. There isn't a unix system-call equivalent for that, because cursor-position *isn't* something the kernel manages at all. It's a terminal concept, implemented by the terminal emulator. (e.g. the program called Terminal on MacOS). You move the cursor on a VT100-compatible terminal by using `write` to send escape sequences. – Peter Cordes Oct 18 '20 at 00:21
  • Right ok, so my follow up then is; how would I go about making use of .bss memory to control the ANSI escape sequence? I have an array of numbers which denotes, say, the columns that I want to print on: is there a way to easily take a number from a register and input it into the control sequence `\033[X;YH`? – Jenna Oct 18 '20 at 00:24
  • And BTW, your attempt to port it to MacOS makes no sense because AH is part of RAX, so `mov ah, 2` is overwritten by `mov rax, 0x02000000 + 0x10`. (IDK where you got 0x10 (16) from, hopefully not the BIOS interrupt number. Also don't know where you got `17` from in the text, that's not in either of your code blocks.) x86-64 MacOS call number 16 (0x10) is `chown`, as your linked table shows. Also, the MacOS system-call ABI never passes any args in RBX. – Peter Cordes Oct 18 '20 at 00:24
  • 2
    Re: formatting into a string: yes, get a buffer and covert integer -> decimal digits. [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) explains how to convert into buffers: *backwards* starting from the end is easiest. Just do that twice, (into bytes before an `'H'`), with a stores of a `';'` in between, and then store a 0o33 and `'['`, ideally as one word store. You can do this on the stack, BTW, but if you do want to use static storage then .bss is the place for it. – Peter Cordes Oct 18 '20 at 00:28
  • Cheers, glad I could help. If you run into trouble, you can edit your question with code for a viable attempt. The voodoo attempt at porting the `int 10h` block to MacOS is probably not a useful starting point for future readers, although you could certainly mention the original int 10h in case future readers are looking for an equivalent to that. Also note that you *could* just keep track of cursor position as you write output, and write full lines with spaces between the things you want in separate columns. (Unless you need to skip existing non-whitespace, e.g. table entries in a grid) – Peter Cordes Oct 18 '20 at 00:35
  • 1
    About your first comment: Creating the string `\033[45;5H` is quite tricky; using a fixed number of digits (`\033[45;05H` or `\033[045;005H` if you want to support terminals wider than 99 columns) is easier: Load the number into the `ax` register and load the value 10 into any other 16-bit register. Perform `div xx` (replace `xx` by the register containing the value 10) and `add dl,0x30`. Now you have the lowest digit (`5` in the case of `045`) as ASCII code in `dl`. Keep the value of `ax`, ensure `xx` contains the value 10 and repeat `div` and `add` to get more digits... – Martin Rosenau Oct 18 '20 at 05:34
  • 1
    @MartinRosenau Recall that for a 16/8 → 8 division, AX is divided into AH:AL, not DL:AL. `aam` could be used here, but unfortunately, it's not available in 64 bit mode. – fuz Oct 18 '20 at 09:10
  • @fuz This is why I wrote that `xx` shall be a 16-bit register. However, I forgot to write that `dx` shall be set to 0 before `div xx`. And of course, it would also be possible to use a 16/8 division instead of a 32/16 one. – Martin Rosenau Oct 18 '20 at 12:08
  • @MartinRosenau: Variable-width is handled easily by generating digits LSD-first, from the end of the string at the end of a long-enough buffer, like I suggested in a comment before yours. When you're done, you know where the start of the string is and can store the 2-byte prefix to the escape code, and pass that address to `write`, with length = end - current, again as shown in that linked answer. – Peter Cordes Oct 18 '20 at 21:15

0 Answers0