1

I am trying to make an x86 assembly macro in NASM that uses ANSI escape codes to move the cursor to the specified X Y coordinates in the user's terminal window. The code is:

; MoveCursor    X,      Y
segment     .data
format:
    db  `\033[%d;%dH` ; First %d is Y coordinate, second %d is X coordinate
                      ; Backticks tell NASM to process these as C-Strings
                      ; Semicolon seperates the Y and X values.
%macro  MoveCursor  2
        lea     rdi,    [rel format]
        lea     rsi,    [rel %2]
        lea     rcx,    [rel %1]    ; ANSI move cursor code is in Y, X format, hence reversing parameters
                                    ; to provide more traditional X,Y format.
        call    _printf ; Print the ANSI code to move the cursor.
        ; printf should have printed something like "\033[1;5H" at this point
%endmacro

You can probably already see my problem. NASM uses Intel syntax, where ";" marks the beginning of a comment. Because of this, NASM thinks everything after the first semicolon in "format" is a comment. Because of this, the macro will change the Y coordinate but not the X coordinate, since where the x coordinate should go is commented out of the printf format. I tried, but (As far as I know. I am no expert in ANSI codes) the ANSI escape code needs that semicolon seperating the two numbers, I can't use whitespace.

Is there any way at all to get around this problem? How can I get properly get that semicolon in "\033[%d;%dH" without NASM thinking it's a comment? Of course, I could write a C++ program to do this and link it with my assembly program, but I would prefer to do it in assembly.

I'm running Mac OSX, and am programming in x86 assembly language. I am using NASM and GCC to compile my program.

Any help will be much appreciated, I'm new here so please tell me if I did anything wrong when writing this question.

SectorSam
  • 253
  • 2
  • 12
  • 1
    NASM shouldn't care about semicolons within quotes. – cHao Sep 26 '18 at 18:41
  • @cHao I would think so too, but when I call the macro using `MoveCursor 5, 10` it changes the Y coordinate but not the x coordinate. – SectorSam Sep 26 '18 at 18:45
  • 3
    \*nix x64 conventions say that the third argument goes in RDX, not RCX. That might have a bit to do with it. – cHao Sep 26 '18 at 18:47
  • @cHao Oh, using RDX fixed it, now it moves to X an Y coordinates, thank you. If you would like, might you post that as an answer so I can give you some reputation for your time? – SectorSam Sep 26 '18 at 18:52
  • 1
    don't forget to zero `al` with `xor eax,eax` before calling `printf`, since you're not passing any FP args in vector registers. – Peter Cordes Sep 26 '18 at 18:55
  • @PeterCordes Helpful as usual! Thank you, I never thought of doing that but that could cause serious problems and morph into the horrible Evanescent bug. – SectorSam Sep 26 '18 at 18:56
  • 1
    use listing file from NASM to verify machine code in such cases (hard to explain bug, where extra hint worth of 5min check is helpful). You would easily see there, that the macros get expanded with full string, and the problem must be elsewhere. :) – Ped7g Sep 26 '18 at 18:59
  • In this case it's actually harmless in practice to leave it out. `printf` will store the first 8 XMM regs to the stack if `al` is non-zero, but never index into that array if it never gets to an FP conversion. (At least that's what happens in glibc `printf`, because that's how gcc compiles variadic C functions. I assume libc on OS X is similar, probably written in C and compiled by clang.) I think the ABI might even say that `al` must be >= number of FP args, not necessarily exactly equal, making it safe to be too high even in theory as well as practice. – Peter Cordes Sep 26 '18 at 18:59

1 Answers1

0

An excellent resource that answers your question perfectly is:

https://github.com/richard-jp-leguen/glorified-typings/blob/master/ta-material/soen228-w2011/tut-01.nasm-programming-for-soen228.md

NASM handles string escapes like a high-level language (C#, JAVA), but slightly different. When pushing your string into the register, make sure to add the ASCII code for an escape, and to add the additional length needed for it.

In that link, you can search for "Can I Use an ASCII code?" , this is where it begins the process of handling escaping the semi-colon.

Richard JP Le Guen
  • 28,364
  • 7
  • 89
  • 119
Kevin B Burns
  • 1,032
  • 9
  • 24