1

I have a function in C performed as follows

 int  rowScreen;  
 int  colScreen;  
 char charac;      
 char tiles[DimMatrix][DimMatrix] = { {'1','2','4'},
                                    {'6','8','A'},                                     
                                    {'C','E',' '} };
void updateBoardP1_C(){
int i, j;
rowScreen = 12;
for (i=0;i<DimMatrix;i++){
  colScreen = 8;
  for (j=0;j<DimMatrix;j++){
     gotoxyP1_C();
     charac = tiles[i][j];
     printchP1_C();
     colScreen = colScreen + 4;
  }
  rowScreen = rowScreen + 2;
 }
 rowScreen = 8;
 colScreen = 20;
 gotoxyP1_C(0);
 charac = moves;
 charac = charac + '0';
 printchP1_C();
}

I change it to assembler and it looks like the following

updateBoardP1_C:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 16
    mov     DWORD PTR rowScreen[rip], 12
    mov     DWORD PTR [rbp-4], 0
    jmp     .L2
.L5:
    mov     DWORD PTR colScreen[rip], 8
    mov     DWORD PTR [rbp-8], 0
    jmp     .L3
.L4:
    mov     eax, 0
    call    gotoxyP1_C
    mov     eax, DWORD PTR [rbp-8]
    movsx   rcx, eax
    mov     eax, DWORD PTR [rbp-4]
    movsx   rdx, eax
    mov     rax, rdx
    add     rax, rax
    add     rax, rdx
    add     rax, rcx
    add     rax, OFFSET FLAT:tiles
    movzx   eax, BYTE PTR [rax]
    mov     BYTE PTR charac[rip], al
    mov     eax, 0
    call    printchP1_C
    mov     eax, DWORD PTR colScreen[rip]
    add     eax, 4
    mov     DWORD PTR colScreen[rip], eax
    add     DWORD PTR [rbp-8], 1
.L3:
    cmp     DWORD PTR [rbp-8], 2
    jle     .L4
    mov     eax, DWORD PTR rowScreen[rip]
    add     eax, 2
    mov     DWORD PTR rowScreen[rip], eax
    add     DWORD PTR [rbp-4], 1
.L2:
    cmp     DWORD PTR [rbp-4], 2
    jle     .L5
    mov     DWORD PTR rowScreen[rip], 8
    mov     DWORD PTR colScreen[rip], 20
    mov     edi, 0
    mov     eax, 0
    call    gotoxyP1_C
    mov     eax, DWORD PTR moves[rip]
    mov     BYTE PTR charac[rip], al
    movzx   eax, BYTE PTR charac[rip]
    add     eax, 48
    mov     BYTE PTR charac[rip], al
    mov     eax, 0
    call    printchP1_C
    nop
    leave
    ret

When wanting to execute this assembly code in 64-bit linux with yasm with this:

yasm -f elf64 -g dwartf2 P1TOC.asm 

throws me the following errors and I don't know how to fix them.

undefined symbol 'PTR'
undefined symbol 'OFFSET'

Is there a way to do the assembly code without PTR and OFFSET? What am I doing wrong?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
willy22
  • 25
  • 5
  • The Intel syntax assembly output from the compiler is not fully compatible with the Intel Syntax of NASM/YASM. Are you using the `-masm=intel` option of the GCC/CLANG compiler when producing this output? – Michael Petch Oct 19 '20 at 18:22
  • @MichaelPetch Yes, I do use -masm = intel, exactly I use this on the linux machine: gcc -S -masm = intel and I still get the .asm file with the PTR and OFFSET. – willy22 Oct 19 '20 at 18:34
  • Not all Intel syntaxes are the same. The output of GCC/CLANG with `-masm=intel` is using PTR and OFFSET which are often used by MASM (Microsoft assembler) Intel syntax but MASM can't assemble it either. I don't know of a program that will do such a conversion between the two. – Michael Petch Oct 19 '20 at 18:37
  • `add rax, OFFSET FLAT:tiles` would become `add rax, tiles` and everywherw there is `PTR` you just remove the `PTR` – Michael Petch Oct 19 '20 at 18:39
  • @MichaelPetch ok, I just removed them and now it tells me "invalid size for operand 2" in the lines: mov eax, DWORD PTR [rbp-8] movsx rcx, eax mov eax, DWORD PTR [rbp-4] movsx rdx, eax – willy22 Oct 19 '20 at 18:49
  • @MichaelPetch Sorry I explained fatally, it gives me the error of operand 2 but without the PTR set, looking like this: mov eax, DWORD [rbp-8] movsx rcx, eax mov eax, DWORD [rbp-4] movsx rdx, eax – willy22 Oct 19 '20 at 19:14
  • 1
    A peculiarity with YASM is that the `movsx` instruction for sign extending 32-bit register to 64-bit register is `MOVSXD` and not `MOVSX`. NASM doesn't have a problem with `MOVSX` as it is smart enough to look at the operands to determine the size in this case. YASM acts dumb in that regard. Change to `movsxd rcx, eax` and `movsxd rdx, eax` – Michael Petch Oct 19 '20 at 19:21
  • 1
    Why do you have to use YASM? Why not just use the GNU assembler to assemble the code? Then you won't have to change anything. – Nate Eldredge Oct 19 '20 at 19:46
  • @MichaelPetch Ok this seems to work! – willy22 Oct 19 '20 at 20:31
  • @NateEldredge How should I do that? Right now I don't understand what I should do. – willy22 Oct 19 '20 at 20:32
  • Instead of building with yasm, you can assemble the file with `gcc -c foo.asm` or `as -o foo.o foo.asm`. Either of those will invoke the GNU assembler (gas) instead of yasm. – Nate Eldredge Oct 19 '20 at 21:15
  • 1
    If you're going to use C compiler output as a starting point for hand-written asm, at least tell it to optimize some, like `-O1` or `-O2`. All that redoing of sign-extension for `int` indices with 64-bit pointers is painful to read and totally unnecessary because they can never be negative. (And `i` and `j` can be kept in registers the whole time, or optimized into pointer increments). [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) – Peter Cordes Oct 20 '20 at 00:51
  • @MichaelPetch: One way to translate is to compile/assemble to machine code, then disassemble with `objconv` into NASM syntax, with the annotations as comments. As shown in [How to generate assembly code with gcc that can be compiled with nasm](https://stackoverflow.com/q/35102193). That would also handle the different syntax for RIP-relative addressing, which this question didn't get to yet. – Peter Cordes Oct 20 '20 at 00:57
  • @PeterCordes How would I do that of -0 to clean the output? How can I remove RIP? – willy22 Oct 20 '20 at 09:02
  • 1
    Run `gcc -O2 -c foo.c` to produce an optimized foo.o. Or `-O2 -S foo.c` to produce an optimized `foo.s` if you decide to follow Nate's suggestion and use GAS instead of NASM/YASM. If you don't know how basic GCC options work, look them up in the GCC manual. Also, you don't want to remove RIP-relative addressing, you just need to use the right syntax for RIP-relative addressing modes in whatever asm syntax you generate. The method shown on [How to generate assembly code with gcc that can be compiled with nasm](https://stackoverflow.com/q/35102193) handles that along with everything else. – Peter Cordes Oct 20 '20 at 09:16

0 Answers0