flat assembler
Message board for the users of flat assembler.

flat assembler > Linux > [solved] Operand sizes do not match!

Author
Thread Post new topic Reply to topic
axlucas



Joined: 02 May 2014
Posts: 66
Location: Argentina
This is the source of a FASM file containing one font blitting routine I made. The idea is to assemble this source and then link the routine together with a FreeBasic program I made. Some time ago, I wrote this routine in 32bit code with the FreeBasic inline assembly and it was working just fine. I can't do the same thing in 64bit, because of some problem between FreeBasic and GAS, so I rewrote the routine for 64bit using Flat Assembler. Anyway, when I trying to FASM it, I get:

Code:
lucas@lucas-compu1:/alt/myproject$ fasm fontblitter.asm
flat assembler  version 1.71.39  (16384 kilobytes memory)
fontblitter.asm [15]:
        mov rdi, [p_to_screen]
error: operand sizes do not match.    


What am I doing wrong? The source is the following:

Code:
format ELF64

section ".routines" executable

_blit_scrwidth = 640

public FONTBLIT
FONTBLIT:
        push rbp
        mov rdi, [p_to_screen]
        mov rdx, [p_to_colour]
        mov rsi, [p_to_font]
        mov cx, [n_of_chars]
        mov rbp, [p_to_text]
        
        .anothercharacter:
                xor rax, rax
                mov al, [rbp]   ; Used to be ds:[ebp]. DS removed because in long mode
                shl rax, 5
                
                push rsi
                add rsi, rax
                
                push rbp
                bswap ecx
                mov ch, 16
                .anotherline:
                        mov ax, [rsi]
                        mov cl, 8
                        .anotherpixel:
                                xor rbx, rbx
                                mov bl, al
                                and bl, 3
                                shl bl, 2
                                add rdx, rbx
                                mov rbp, [rdx]
                                sub rdx, rbx
                                mov [rdi], rbp
                                add rdi, 4
                                shr rax, 2
                                dec cl
                                jnz .anotherpixel
                        add rsi, 2
                        add rdi, _blit_scrwidth * 4 - 32
                        dec ch
                        jnz .anotherline
                pop rbp
                pop rsi
                inc rbp
                sub rdi, _blit_scrwidth * 64 - 32
                bswap ecx
                dec cx
                jnz .anothercharacter
        pop rbp
        ret

section ".data" writeable

public p_to_screen      ; Pointers
public p_to_colour
public p_to_font
public p_to_text
public n_of_chars       ; Number of characters

p_to_screen dp 0
p_to_colour dp 0
p_to_font dp 0
p_to_text dp 0
n_of_chars dw 0    


I'm sure I must be doing something very stupidly simple, but I'm really confused. Never coded for 64bit Linux before. Thanks in advance!
Post 14 Aug 2015, 21:31
View user's profile Send private message Reply with quote
axlucas



Joined: 02 May 2014
Posts: 66
Location: Argentina
Ha, ha! Found it! I thought "dp" was the size of a pointer, that is, either 32 or 64 bit depending on the architecture, but it's 48 bit (16 bit for a segment and 32 bit for a 32 bit offset). I replaced it with dq and it works fine, except that there's a one pixel offset I still don't know why, but I guess I'm about to figure out. Anyway, comments are appreciated!
Post 14 Aug 2015, 21:40
View user's profile Send private message Reply with quote
SeproMan



Joined: 11 Oct 2009
Posts: 54
Location: Belgium
Glad you found the solution for the dp directive yourself.


You wrote the following:

Code:
add rdx, rbx
mov rbp, [rdx] 
sub rdx, rbx    


Might I suggest this simplification:

Code:
mov ebp, [rdx + rbx]    


If you want you can shave off the pushing and popping of the RBP register through using:

Code:
mov ebx, [rdx + rbx]    



Please note that I changed the destination register to 32 bits because that's where the error in your program lies! You need only 32 bits to store in the video RAM.

Code:
mov [rdi], ebx
add rdi, 4    



I don't know if you are interested in code optimizations but here are a couple of them:
    Instead of clearing RBX and later anding BL, why not combine both actions?
    Instead of left shifting BL 2 times why not do this with a scaled index address form?


Doing so would produce the following code:
Code:
mov bl, al
and rbx, 3
mov ebx, [edx + rbx * 4]
mov [rdi], ebx
add rdi, 4    


If code size matters you can use STOSD provided you exchange the uses of the A and B registers in this part of your code:

Code:
.anotherline: 
  mov bx, [rsi] 
  mov cl, 8 
  .anotherpixel: 
    mov al, bl 
    and rax, 3                <--- Oops!
    mov eax, [rdx + rax * 4]  <--- Oops!
    stosd ;Be sure DirectionFlag is cleared beforehand
    shr bx, 2 
    dec cl 
    jnz .anotherpixel    

_________________
Real Address Mode.


Last edited by SeproMan on 16 Aug 2015, 13:57; edited 1 time in total
Post 15 Aug 2015, 19:30
View user's profile Send private message Reply with quote
axlucas



Joined: 02 May 2014
Posts: 66
Location: Argentina
SeproMan. If I just say "thank you", you won't get the idea of how much I appreciate your comments.

Before I came back here, I did figure out that I was moving a whole quad instead of the 32 bits of colour data, which caused the last pixel to show up as a vertical line to the right of my characters. I had made this error because, as I said before, I translated this routine from one I had made for 32 bits before, so I instinctively changed all 32bit regs to 64bit regs. I do see how significant it is that you have noticed this error quickly too, considering that you're not seeing my program running and that this is the very first time you read my code!

About optimisations, while it's true that today's computers are really fast and have tons of memory and disk space and small changes are probably come unnoticed on these systems, I will be glad to implement these. Having to rely on a high level language most of the time is not something I enjoy and I long for the times when we had to be careful about our use of resources, because that made us better programmers. I want to continue to practise that, whether it will be noticed or not. By the way, I'd like to program for some more low-level platform than the PC.... I'll write another post on that. Cheers, mate! Smile
Post 15 Aug 2015, 21:06
View user's profile Send private message Reply with quote
SeproMan



Joined: 11 Oct 2009
Posts: 54
Location: Belgium
axlucas, I just saw I made an error in my last code snippet!
I fogot to exchange RBX for RAX 2 times. I edited the post.
Here's the correct version:

Code:
.anotherline:
  mov bx, [rsi]
  mov cl, 8
  .anotherpixel:
    mov al, bl
    and rax, 3
    mov eax, [rdx + rax * 4] 
    stosd ;Be sure DirectionFlag is cleared beforehand 
    shr bx, 2
    dec cl
    jnz .anotherpixel    
Post 16 Aug 2015, 14:03
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2019, Tomasz Grysztar.

Powered by rwasa.