1

I am trying to run the code below to update the position of the cursor in my OS, I've been trying everything I could for about a month, including every possible solution I could find online, but nothing is working.

void updateCursor(short x_val, short y_val, short w_val) {
    //% = argument, $ = immediate, %% register
    __asm__(
        "  mov %%ax,%1\n"
        "  mov %%bx,%0\n"
        "  mov %%dl,%2\n"
        "  mul %%dl\n"
        "  add %%bx,%%ax\n"
        "  mov %%dx,$0x03D4\n"
        "  mov %%al,$0x0F\n"
        "  out %%dx,%%al\n"
        "  inc %%dl\n"
        "  mov %%al,%%bl\n"
        "  out %%dx,%%al\n"
        "  dec %%dl\n"
        "  mov %%al,$0x0E\n"
        "  out %%dx,%%al\n"
        "  inc %%dl\n"
        "  mov %%al,%%bh\n"
        "  out %%dx,%%al\n"
        ://would be return stuff here using =g instead of g like below, starting with %0
        :"r" (x_val), "r" (y_val), "r" (w_val)  //start at the first index after output
        : //Overwritten registers ("Clobber list")
    );
    
}

The error is

./src/kernel/terminal.c:73: Error: unsupported instruction `mov'
./src/kernel/terminal.c:76: Error: unsupported instruction `mov'
./src/kernel/terminal.c:77: Error: unsupported instruction `mov'
./src/kernel/terminal.c:78: Error: operand type mismatch for `out'
./src/kernel/terminal.c:81: Error: operand type mismatch for `out'
./src/kernel/terminal.c:83: Error: unsupported instruction `mov'
./src/kernel/terminal.c:84: Error: operand type mismatch for `out'
./src/kernel/terminal.c:87: Error: operand type mismatch for `out'
./src/kernel/terminal.c:73: Error: unsupported instruction `mov'
./src/kernel/terminal.c:76: Error: unsupported instruction `mov'
./src/kernel/terminal.c:77: Error: unsupported instruction `mov'
./src/kernel/terminal.c:78: Error: operand type mismatch for `out'
./src/kernel/terminal.c:81: Error: operand type mismatch for `out'
./src/kernel/terminal.c:83: Error: unsupported instruction `mov'
./src/kernel/terminal.c:84: Error: operand type mismatch for `out'
./src/kernel/terminal.c:87: Error: operand type mismatch for `out'

I'm really confused where the problem is, because its not the logic of the assembly as this works fine to set the position at the start

;updating cursor at the start
    mov ax, 0
    mov bx, 5

    mov dl, 80
    mul dl
    add bx, ax
    mov dx, 0x03D4
    mov al, 0x0F
    out dx, al
    
    inc dl
    mov al, bl
    out dx, al
    
    dec dl
    mov al, 0x0E
    out dx, al
    
    inc dl
    mov al, bh
    out dx, al

and it's not my use of __asm__ as this works fine

int exampleAsm() {
    int joe=3, fred;
    __asm__(
        "  mov %1,%%eax\n"
        "  add $2,%%eax\n"
        "  mov %%eax,%0\n"
        :"=r" (fred) /* %0: Output variable list */
        :"r" (joe) /* %1: Input variable list */
        :"%eax" /* Overwritten registers ("Clobber list") */
    );
    return fred;
}

So any help is greatly appreciated, I think the problem is something to do with the number of bits, but i tried compiling with -m32 and that didn't work, and I've tried using int and char instead of short and that didn't work


Solution: GCC uses a whole new syntax of assembly, the differences are more than just adding % or $. I used this link to help me. Corrected code is following.

void updateCursor(short x_val, short y_val, uint8_t w_val) {
    //% = argument, $ = immediate, %% register
    __asm__(
        "  movw %1, %%ax\n"
        "  movw %0, %%bx\n"
        "  movb %2, %%dl\n"
        "  mul %%dl\n"
        "  addw %%ax, %%bx\n"
        "  movw $0x03D4, %%dx\n"
        "  movb $0x0F, %%al\n"
        "  out %%al, %%dx\n"
        "  inc %%dl\n"
        "  movb %%bl, %%al\n"
        "  out %%al, %%dx\n"
        "  dec %%dl\n"
        "  movb $0x0E, %%al\n"
        "  out %%al, %%dx\n"
        "  inc %%dl\n"
        "  movb %%bh, %%al\n"
        "  out %%al, %%dx\n"
        ://would be return stuff here using =g instead of g like below, starting with %0
        :"g" (x_val), "g" (y_val), "g" (w_val)  //start at the first index after output
        : "%ax", "%bx", "%dx" //Overwritten registers ("Clobber list")
    ); 
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    It seems that you've just added `%` to all the register names without noting the many other important differences in AT&T syntax assembly. Most notably, operand order is usually reversed from Intel. So for instance `add bx, ax` becomes `add %%ax, %%bx`. – Nate Eldredge Apr 30 '22 at 21:51
  • You also have a comment about needing clobbers but have not actually included them: you need clobbers for `ax, bx, dx`. – Nate Eldredge Apr 30 '22 at 21:53
  • Thank you, I feel so stupid for not realising that it was another syntax of assembly, I thought the % were just things for gcc to pass in arguments, didn't realise there could be other differences. I added w to all mov's or add's that involved ax bx or dx, the rest i added b, and then swapped the order of all arguments. I also changed w_val to a uint8_t since i wanted to set it to a one byte register, not sure if I needed too but figured it was good practice anyway. – SpartanSpark Apr 30 '22 at 22:11
  • @SpartanSpark it's better to use `.intel_syntax noprefix` and `-masm=intel` to tell gas to use Intel syntax, no need to convert to AT&T syntax. See [Can I use Intel syntax of x86 assembly with GCC?](https://stackoverflow.com/q/9347909/995714) – phuclv May 01 '22 at 01:31
  • @phuclv: `.intel_syntax noprefix` only in stand-alone `.S` files. `-masm=intel` alone is sufficient for inline asm in C, and you should *not* use a `.intel_syntax noprefix` directive in inline asm. (You'd need to switch back to `.att_syntax` at the end, which would break things if you did compile with `-masm=intel`. But just using directives means the compiler substitutes AT&T register names, memory operands, and constants, not Intel which only sometimes happens to work with GCC, not clang.) – Peter Cordes May 01 '22 at 02:02

0 Answers0