I just started trying to learn assembly, and thought that I would test using it on the Prizm with this program:


Code:

int main(void) {
    __asm__ ( "movl $10, %eax;"
    );
   return 0;
}


Unfortunately, this doesn't even compile, and I get the following error:


Code:

      1 [main] [ 2176 find_fast_cwd: WARNING: Couldn't compute FAST_CWD pointer.  Please report this problem to
the public mailing list cygwin@cygwin.com
sh3eb-elf-gcc -MMD -MP -MF C:/Users/Admin/Documents/PrizmDev/PrizmSDK-0.3/projects/AsmTest/build/AsmTest.d -Os -Wall -mb -m4a-nofpu -mhitachi -nostdlib   -IC:/Users/Admin/Documents/PrizmDev/PrizmSDK-0.3/projects/AsmTest/build -IC:/Users/Admin/Documents/PrizmDev/PrizmSDK-0.3/include -c C:/Users/Admin/Documents/PrizmDev/PrizmSDK-0.3/projects/AsmTest/src/AsmTest.c -o AsmTest.o
C:\Users\Admin\AppData\Local\Temp\ccCXOr0z.s: Assembler messages:
C:\Users\Admin\AppData\Local\Temp\ccCXOr0z.s:9: Error: unknown opcode
make[1]: *** [AsmTest.o] Error 1
make: *** [build] Error 2


From what I've read, GCC uses the AT&T syntax, so I'm not sure what is wrong here.
%eax is an x86 register, and movl is an x86 mnemonic. As noted on our Casio Prizm information page, the Casio Prizm has an SH3/4 processor, which means that you need to write SH3/4 ASM for it.
That code will run better on a Casio Algebra FX.

http://www.pageofmarco.de/afxinfo.php

Wink
It won't even then! 32-bit registers weren't introduced until the '386. Smile

(We digress, though.)
bhtooefr wrote:
That code will run better on a Casio Algebra FX.

http://www.pageofmarco.de/afxinfo.php

Wink


I read about this calculator at Marcos' AFX site. Very interesting hardware and possibly an easier platform on which to develop.

Is this calculator still being made by Casio ?
I have been using this routine to help me learn prizm assembly (http://www.cemetech.net/forum/viewtopic.php?t=9740&highlight=), but I don't understand what is going on with the .align instructions:


Code:

void pixel_asm(unsigned short x, unsigned short y, unsigned short color)
{
    __asm__("mov.w   .width,r1\n"    // width -> r1
            "mulu.w   r1,r5\n"        // width * y -> macl    : Get the y pixel offset
            "mov.l   .vram,r1\n"     // vram -> r1           : Sets the VRAM adres in r1
            "sts   macl,r0\n"      // macl -> r0           : Gets macl in r0
            "add   r4,r0\n"        // r0 + x -> r0         : Get the pixel offset in the VRAM
            "shll   r0\n"           // r0 = r0 <<1          : Multiplies by two to get the short offset
            "mov.w   r6,@(r0,r1)\n"  // *(r0+r1) = color          : Sets the pixel to the desired color
            "rts\n"   
            "clrmac\n"
            ".align 1\n"
            ".width:\n"
            "    .short 384\n"
            "     .align 2\n" 
            ".vram:\n"
            "    .long -1476395008\n"
            "    .align 1\n");
}


From what I've read, (http://stackoverflow.com/questions/11277652/what-is-the-meaning-of-align-an-the-start-of-a-section) .align is used to optimize the placement of data, but must also be a power of two. What are the .align 1 instructions for? The code compiles without them, but it doesn't without the .align 2 instruction.
.align refers to placing data that are aligned on word boundaries. For example, .align 2 can place a value at addresses % 2 == 0, such as 0x8000, 0x8002, 0x8004..., .align 4 places values at addresses at % 4 == 0, such as 0x8000, 0x8004, 0x8008...

This is because opcodes for the Prizm that operate on words and dwords directly in memory may need to access values on aligned addresses.

Possibly .align sets the alignment state and .align 1 resets it? I haven't done anything in assembly for SuperH.
In the SH-4 and SH-4A software manuals it lists these three .align instructions:

.align 2
2-byte boundary alignment
.align 4
4-byte boundary alignment
.align 32
32-byte boundary alignment

However, it never mentions .align 1, nor is it used in any examples.
My guess would be that .align 1 is 1-byte boundary alignment. The reason it still works when you remove them is because 1-byte boundary alignment is meaningless.
The machine requires that memory accesses be aligned to their size, so byte access has no alignment restrictions, halfword (16-bit) requires that bit 0 of the address be clear, and word access requires that the low two bits be clear. Unaligned accesses cause a fault at runtime.

gas is unfortunately rather indecisive when it comes to interpretation of the .align directive; I'm assuming the alignment parameter for SH is in bits, since the docs don't call it out as a system in which the alignment is specified in bytes.

With that in mind, we can dissect it a bit:
Code:
mov.w .width, r1

.align 1
.width: .short 384
We load a 16-bit value from memory at width into r1. Since it's a 16-bit load, we must ensure the value is aligned with bit 0 of its address clear.


Code:
mov.l .vram, r1

.align 2
.vram: .long -1476395008
.align 1
Same deal, except it's a 32-bit value so must have the low-order two bits clear. The trailing align directive is useless- not only will the toolchain handle alignment for code as necessary outside this function, but a 4-byte-aligned value such as this one is also 2-byte-aligned by definition.
From what I've seen the docs do call it out as byte alignment.

".align 2
2-byte boundary alignment
.align 4
4-byte boundary alignment
.align 32
32-byte boundary alignment "

is directly from the SH-4A software manual. Another thing that confuses me about this code is the clrmac instruction. I understand it clears the multiplication accumulator, but in this version I re-wrote:

Code:

void pixel_asm(unsigned short color)
{
    __asm__("mov      #2,r0;"    // 0 -> r0
            "mov.l      .vram,r1;"     // vram -> r1           : Sets the VRAM address in r1
            "shll      r0;"           // r0 = r0 <<1          : Multiplies by two to get the short offset
            "mov.w      r4,@(r0,r1);"  // *(r0+r1) = color          : Sets the pixel to the desired color
            "rts      ;"   
            "clrmac      ;"
            ".align      2;" 
            ".vram:        ;"                                     
            ".long      -1476395008;"
         );
}

The accumulator isn't used, yet if the clear instruction isn't called the program causes the calculator to crash.
Official docs don't apply to GNU tools, which I assume you're using (since we don't use the official tools at all). I did some experiments, and it appears to be bitmask-based as I had guessed.

align.S:
Code:
    nop

.align A1
    .short 0xFFFF

.align A2
    .long 0xFFFFFFFF


Build:

Code:
$ sh3eb-elf-gcc -c -DA1=0 -DA2=0 align.S

Disassemble:

Code:
$ sh3eb-elf-objdump -D align.o


Now we can experiment with different alignments for the values and see what falls out.

A1=0, A2=0: packed as expected.

Code:
00000000 <.text>:
   0:   00 09           nop
   2:   ff ff           .word 0xffff
   4:   ff ff           .word 0xffff
   6:   ff ff           .word 0xffff


A1=1, A2=1: no change; all values are already aligned at even addresses.

A1=2, A2=1: assembler notices (!) and bails out; the value at A2 would be placed at offset 6:

Code:
align.S: Assembler messages:
align.S:8: Error: misaligned data


A1=2, A2=2: both values aligned with bits 0 and 1 clear:

Code:
00000000 <.text>:
   0:   00 09           nop
   2:   00 09           nop
   4:   ff ff           .word 0xffff
   6:   00 09           nop
   8:   ff ff           .word 0xffff
   a:   ff ff           .word 0xffff


A1=3, A2=2: still a 16-bit gap between A1 and A2 values as expected, A1 is now pushed back 6 bytes to clear the lower 3 bits:

Code:
00000000 <.text>:
   0:   00 09           nop
   2:   00 09           nop
   4:   00 09           nop
   6:   00 09           nop
   8:   ff ff           .word 0xffff
   a:   00 09           nop
   c:   ff ff           .word 0xffff
   e:   ff ff           .word 0xffff


That seems pretty conclusive to me. A really obvious example with A1=4, A2=8:

Code:
00000000 <.text>:
   0:   00 09           nop
[snip]
   e:   00 09           nop
  10:   ff ff           .word 0xffff
  12:   00 09           nop
[snip]
  fe:   00 09           nop
 100:   ff ff           .word 0xffff
 102:   ff ff           .word 0xffff
Ygyaxthe3rd wrote:
Another thing that confuses me about this code is the clrmac instruction. I understand it clears the multiplication accumulator, but in this version I re-wrote:

Code:

void pixel_asm(unsigned short color)
{
    __asm__("mov      #2,r0;"    // 0 -> r0
            "mov.l      .vram,r1;"     // vram -> r1           : Sets the VRAM address in r1
            "shll      r0;"           // r0 = r0 <<1          : Multiplies by two to get the short offset
            "mov.w      r4,@(r0,r1);"  // *(r0+r1) = color          : Sets the pixel to the desired color
            "rts      ;"   
            "clrmac      ;"
            ".align      2;" 
            ".vram:        ;"                                     
            ".long      -1476395008;"
         );
}

The accumulator isn't used, yet if the clear instruction isn't called the program causes the calculator to crash.


That's because RTS has a delay slot, which means the following instruction is executed before actually returning. If you replace the CLRMAC with a NOP or the MOV.W instruction, I think it would no longer crash. (An RTS with nothing specified after is a bad idea, since you'll be executing an arbitrary instruction or data after it.)
How would I go about moving the value of a C variable into a register from an inline assembly block? I imagine it would involve finding the variable's location in memory, but I have no idea as to how that would be done.
You have to use some features provided by GCC inline assembly : http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#toc5
You can see here for exemple, section extended assembly Smile.

If you want an exemple of how it works with SH asm, i've got a project where I use it in the add_byte function https://github.com/Nemhardy/chip8/blob/master/src/instructions.c
If you dont understand, just ask. Smile

Édit: doing some correction because my grammar corrector doesn't handle English very well :p
ti83head wrote:
bhtooefr wrote:
That code will run better on a Casio Algebra FX.

http://www.pageofmarco.de/afxinfo.php

Wink


I read about this calculator at Marcos' AFX site. Very interesting hardware and possibly an easier platform on which to develop.

Is this calculator still being made by Casio ?


No it isn't, and that is actually kind of sad. It was a really great calculator.
I am looking at one on a popular auction site. What cable is required to link between the calculator and a PC ? I have 9860 and the USB linking cable for that particular model but I guess the FX is different ?
It's standard USB mini-A AFAIK.

Edit: I misunderstood your question apparently, assuming FX -> FX-CG.
The AFX connects through 3-pin only. It doesn't have a USB connector and you'll need a special 3-pin<->serial cable (and eventually a serial-to-USB adapter if your computer doesn't have a serial port). See http://www.casiopeia.net/forum/viewtopic.php?f=20&t=1473

EDIT (reply to Tari): indeed, "FX" can refer to basically all the Casio calculators, even the scientific and very old ones.
Nemhardy; I followed your example and read that article on gcc inline assembly, but the code I've written doesn't work.


Code:

int main(void)
{
unsigned short color = COLOR_BLACK;
int x=0,y=0;

for(j=0;j< 10;j++)
   {
        __asm__(   "mov.w      .width,r1;"
               "mulu.w     r1,%[y];"
               "mov.l      .vram,r1;"
               "sts         macl,r0;"
               "add         %[x],r0;"
               "shll      r0;"
               "mov.w      %[color],@(r0,r1);"
               "clrmac      ;"
               ".align 1   ;"
               ".width:   ;"
               ".short    384;"
               ".align      2;"
               ".vram:      ;"
               ".long       -1476395008;"
               :// no output
               :[x]"r"(x),[y]"r"(y),[color]"r"(color)
               :"r0","r1"
               );
   }
return 0;
}


Do you have any idea what the problem is? it compiles fine, but when I run it on my calculator it causes a crash.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
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

 

Advertisement