Le génial Ndless nous le permettant, voici mon tout premier programme en Assembleur pour TI nspire

(la mienne est une CX CAS, donc , à voir si c'est compatible sur les autres nspire ..?)
Avec Ndless installé préalablement, bien sûr

Comme je ne savais pas (encore) comment afficher via une routine système, je me suis mis à ré-écrire ma routine d'affichage en segments, tout en m'initiant à ce nouveau langage Assembleur.
Dans la foulée, j'ai programmé un petit compte-à-rebours, également une routine d'effaçage-écran, et une autre de temporisation.
- Code: Select all
.asciz "PRG" /* en-tête "PRG" */
stmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
mov r0,#0xC0000018
ldr r1,[r0]
eor r1,#0b1000 /* change le bit3 pour passer en mode 4bpp */
str r1,[r0]
bl CLR_SCREEN /* routine d'éffaçage écran */
mov r3,#0x00100000 /* valeur de départ du compteur */
mov r0,#0 /* affiché en position 0 (c-à-d coin sup.gauche) */
anim_lp: bl HEX_SEG
subs r3,#1
bne anim_lp
bl HEX_SEG /* pour afficher la valeur finale "00000000" */
bl PAUSE_2s
ldmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
/***************************************************/
HEX_SEG: /* ROUTINE D'AFFICHAGE 32bits (en hexadécimale) */
/* r3 = valeur à afficher */
/* r0 = offset de la position en mémoire-écran */
/* NB: Tous les registres sont préservés */
/***************************************************/
stmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
mov r1,#0xC0000010
ldr r1,[r1]
add r0,r0,r1
add r0,#28
mov r4,#8 /* 8 segments à afficher */
decomp: mov r1,r3
and r1,#0xF
adr r2,hex_data
ldr r2,[r2,+r1,lsl#2]
mov r5,#2 /* on affichera 2x un groupe de 3 segments (en "n") */
mov r7,#0
main_lp: adds r2,r2
movmi r7,#0x0FFFFFF0
str r7,[r0] /* trace le segment horizontal supérieur */
addmi r0,#160
mov r6,#5
submi r6,#1 /* Longs de 4 à 5 pixels, on trace les 2 */
mov r7,#0 /* segments verticaux en même temps */
adds r2,r2
orrmi r7,#0x000000F0
adds r2,r2
orrmi r7,#0x0F000000
verti_lp: str r7,[r0],#160
subs r6,#1
bne verti_lp
subs r5,#1
bne main_lp
adds r2,r2
movmi r7,#0x0FFFFFF0
str r7,[r0],#-1604 /* enfin, le segment horizontal du bas */
subs r4,#1
movne r3,r3,ror#4
bne decomp
ldmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
hex_data: .word 0b1110111000000000000000000000000 /* 0 */
.word 0b0010010000000000000000000000000 /* 1 */
.word 0b1011101000000000000000000000000 /* 2 */
.word 0b1011011000000000000000000000000 /* 3 */
.word 0b0111010000000000000000000000000 /* 4 */
.word 0b1101011000000000000000000000000 /* 5 */
.word 0b1101111000000000000000000000000 /* 6 */
.word 0b1010010000000000000000000000000 /* 7 */
.word 0b1111111000000000000000000000000 /* 8 */
.word 0b1111011000000000000000000000000 /* 9 */
.word 0b1111110000000000000000000000000 /* A */
.word 0b0101111000000000000000000000000 /* b */
.word 0b1100101000000000000000000000000 /* C */
.word 0b0011111000000000000000000000000 /* d */
.word 0b1101101000000000000000000000000 /* E */
.word 0b1101100000000000000000000000000 /* F */
/***************************************************************/
PAUSE_2s: stmfd sp!,{r0,lr}
mov r0,#0x4000000 /* (2^24)*4 pour 2 secondes */
wait_lp: subs r0,#1
bne wait_lp
ldmfd sp!,{r0,pc}
/***************************************************************/
CLR_SCREEN: stmfd sp!,{r0,r1,r2,lr}
mov r0,#0xC0000010
ldr r0,[r0] /* r0 = mémoire-écran */
mov r1,#0 /* couleur 0, donc en noir */
mov r2,#9600
clr_lp: str r1,[r0],#4
subs r2,#1
bne clr_lp
ldmfd sp!,{r0,r1,r2,pc}
/***************************************************************/
Comme j'utilise désormais un Raspberry pi (modèle 2, B+) sous raspbian, j'ai tout naturellement profité de son microprocesseur ARM pour développer en Assembleur.
J'utilise GNU Assembleur en ligne de commande:
- Code: Select all
as -aln -mcpu=arm926ej-s -o temp.o countdown.s && objcopy -O binary temp.o countdown.prg.tns && rm temp.o
EDIT: Si vous n'êtes pas sur Raspberry Pi, mais sur un PC x86/x64 sous linux à base d' Ubuntu/Debian, il va falloir "cross-assembler" : installer préalablement la version ARM de l'assembleur AS que contient GCC (en tapant sudo apt-get install gcc-arm-linux-gnueabihf )
Puis entrer...
- Code: Select all
arm-linux-gnueabihf-as -aln -mcpu=arm926ej-s -o temp.o countdown.s && arm-linux-gnueabihf-objcopy -O binary temp.o countdown.prg.tns && rm temp.o
Ce qui nous donne...
- Code: Select all
1
2 0000 50524700 .asciz "PRG" /* en-tête "PRG" */
3
4 0004 FF5F2DE9 stmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
5
6 0008 6301A0E3 mov r0,#0xC0000018
7 000c 001090E5 ldr r1,[r0]
8 0010 081021E2 eor r1,#0b1000 /* change le bit3 pour passer en mode 4bpp */
9 0014 001080E5 str r1,[r0]
10
11 0018 3F0000EB bl CLR_SCREEN /* routine d'éffaçage écran */
12
13 001c 0136A0E3 mov r3,#0x00100000 /* valeur de départ du compteur */
14 0020 0000A0E3 mov r0,#0 /* affiché en position 0 (c-à-d coin sup.gauche)
15 0024 040000EB anim_lp: bl HEX_SEG
16 0028 013053E2 subs r3,#1
17 002c FCFFFF1A bne anim_lp
18 0030 010000EB bl HEX_SEG /* pour afficher la valeur finale "00000000" */
19
20 0034 330000EB bl PAUSE_2s
21
22 0038 FF9FBDE8 ldmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
23
24 /***************************************************/
25 HEX_SEG: /* ROUTINE D'AFFICHAGE 32bits (en hexadécimale) */
26 /* r3 = valeur à afficher */
27 /* r0 = offset de la position en mémoire-écran */
28 /* NB: Tous les registres sont préservés */
29 /***************************************************/
30 003c FF5F2DE9 stmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
31 0040 4311A0E3 mov r1,#0xC0000010
32 0044 001091E5 ldr r1,[r1]
33 0048 010080E0 add r0,r0,r1
34 004c 1C0080E2 add r0,#28
35 0050 0840A0E3 mov r4,#8 /* 8 segments à afficher */
36 0054 0310A0E1 decomp: mov r1,r3
37 0058 0F1001E2 and r1,#0xF
38 005c 64208FE2 adr r2,hex_data
39 0060 012192E7 ldr r2,[r2,+r1,lsl#2]
40 0064 0250A0E3 mov r5,#2 /* on affichera 2x un groupe de 3 segments (en "n")
41 0068 0070A0E3 mov r7,#0
42 006c 022092E0 main_lp: adds r2,r2
43 0070 FF72E043 movmi r7,#0x0FFFFFF0
44 0074 007080E5 str r7,[r0] /* trace le segment horizontal supérieur */
45 0078 A0008042 addmi r0,#160
46 007c 0560A0E3 mov r6,#5
47 0080 01604642 submi r6,#1 /* Longs de 4 à 5 pixels, on trace les 2 */
48 0084 0070A0E3 mov r7,#0 /* segments verticaux en même temps */
49 0088 022092E0 adds r2,r2
50 008c F0708743 orrmi r7,#0x000000F0
51 0090 022092E0 adds r2,r2
52 0094 0F748743 orrmi r7,#0x0F000000
53 0098 A07080E4 verti_lp: str r7,[r0],#160
54 009c 016056E2 subs r6,#1
55 00a0 FCFFFF1A bne verti_lp
56 00a4 015055E2 subs r5,#1
57 00a8 EFFFFF1A bne main_lp
58 00ac 022092E0 adds r2,r2
59 00b0 FF72E043 movmi r7,#0x0FFFFFF0
60 00b4 447600E4 str r7,[r0],#-1604 /* enfin, le segment horizontal du bas */
61 00b8 014054E2 subs r4,#1
62 00bc 6332A011 movne r3,r3,ror#4
63 00c0 E3FFFF1A bne decomp
64 00c4 FF9FBDE8 ldmfd sp!,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
65
66 00c8 00000077 hex_data: .word 0b1110111000000000000000000000000 /* 0 */
67 00cc 00000012 .word 0b0010010000000000000000000000000 /* 1 */
68 00d0 0000005D .word 0b1011101000000000000000000000000 /* 2 */
69 00d4 0000005B .word 0b1011011000000000000000000000000 /* 3 */
70 00d8 0000003A .word 0b0111010000000000000000000000000 /* 4 */
71 00dc 0000006B .word 0b1101011000000000000000000000000 /* 5 */
72 00e0 0000006F .word 0b1101111000000000000000000000000 /* 6 */
73 00e4 00000052 .word 0b1010010000000000000000000000000 /* 7 */
74 00e8 0000007F .word 0b1111111000000000000000000000000 /* 8 */
75 00ec 0000007B .word 0b1111011000000000000000000000000 /* 9 */
76 00f0 0000007E .word 0b1111110000000000000000000000000 /* A */
77 00f4 0000002F .word 0b0101111000000000000000000000000 /* b */
78 00f8 00000065 .word 0b1100101000000000000000000000000 /* C */
79 00fc 0000001F .word 0b0011111000000000000000000000000 /* d */
80 0100 0000006D .word 0b1101101000000000000000000000000 /* E */
81 0104 0000006C .word 0b1101100000000000000000000000000 /* F */
82
83 /***************************************************************/
84
85 0108 01402DE9 PAUSE_2s: stmfd sp!,{r0,lr}
86 010c 0103A0E3 mov r0,#0x4000000 /* (2^24)*4 pour 2 secondes */
87 0110 010050E2 wait_lp: subs r0,#1
88 0114 FDFFFF1A bne wait_lp
89 0118 0180BDE8 ldmfd sp!,{r0,pc}
90
91 /***************************************************************/
92
93 011c 07402DE9 CLR_SCREEN: stmfd sp!,{r0,r1,r2,lr}
94 0120 4301A0E3 mov r0,#0xC0000010
95 0124 000090E5 ldr r0,[r0] /* r0 = mémoire-écran */
96 0128 0010A0E3 mov r1,#0 /* couleur 0, donc en noir */
97 012c 962DA0E3 mov r2,#9600
98 0130 041080E4 clr_lp: str r1,[r0],#4
99 0134 012052E2 subs r2,#1
100 0138 FCFFFF1A bne clr_lp
101 013c 0780BDE8 ldmfd sp!,{r0,r1,r2,pc}
102
103 /***************************************************************/
Ainsi, partant du fichier-texte countdown.s , GNU Assembleur nous ponds countdown.prg.tns, exécutable sur la TI nspire ! C'est cool, non ?

C'est sûr qu'il y a plus pratique (via un script, j'imagine...) mais pour l'instant , je m'en contente

Désolé pour le screenshot, je n'ai pas pu en faire : dès la fin du programme, la TI nspire rétablit d'office l'écran

(et je n'ai pas firebird emu)
Téléchargeable ici : archives_voir.php?id=640485