Groupe 4 — Mathématiques Officiel
4,0 Addition · 4,1 Subtraction · 4,2 Multiplication · 4,3 Decimal Division · 4,4 Integer Division · 4,5 Integer Modulus · 4,6 Compare · 4,7 Power · 4,8 Distance (counter-rectangle) · 4,9 Angle calculation (arctangent2) · 4,16 Negate · 4,17 Floor · 4,18 Square Root · 4,19 Sine · 4,20 Cosine · 4,21 Tangent · 4,22 Arctangent · 4,23 Exponent · 4,24 Logarithm · 4,25 Absolute Value · 4,26 Sign · 4,27 Random Decimal · 4,28 Random Integer · 4,32 Number to Decimal · 4,33 String to Number · 4,34 Number to String · 4,35 Set Degree/Radian Mode
Le groupe 4 est un coprocesseur de calcul : le RP2040 calcule en entiers 32 bits ou en flottants simple précision (IEEE 754) pour le 65C02. Les nombres ne passent pas par la boîte aux lettres mais par deux registres rangés dans la mémoire du 65C02, dont chaque appel donne l'adresse.
Un registre fait 5 octets : un octet de type ($00 entier, $40 flottant), puis les 4 octets de la valeur, poids faible d'abord. P0-P1 donne l'adresse de l'octet de type du registre 1 ; celui du registre 2 est à l'octet suivant. P2 donne le pas entre deux octets d'un même registre : avec un pas de 2, les deux registres sont entrelacés sur 10 octets (types, puis octets 0 des deux valeurs, puis octets 1…). C'est la disposition des exemples, et celle de l'unité neo6502math de Mad Pascal ; NeoBASIC y range sa pile d'expressions.
Le résultat revient dans le registre 1, avec son type. Une opération à deux registres calcule en flottant dès qu'un des deux est flottant, en entier sinon. Pour afficher un résultat, les exemples le convertissent en texte avec 4,34, ce qui donne le format du firmware (6 décimales pour un flottant).
Les angles sont en degrés par défaut ; 4,35 passe en radians. Le démarrage d'un programme Mad Pascal passe en radians (code de démarrage de Mad Pascal 1.7.8) : les exemples Pascal qui utilisent des angles repassent en degrés.
4,0 Addition Officiel
Registre 1 := registre 1 + registre 2.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | somme (flottant si un opérande l'est) |
Unité neo6502math de Mad Pascal (version 0.30.0) : SetMathStack(v, 0) écrit aussi la position 1 (le code de la position 0 continue sur celui de la position 1). Il faut donc donner la position 0 avant la position 1 ; dans l'autre ordre, les deux registres valent le premier nombre (vérifié : 7 \ 2 donne alors 1). En NeoBASIC, + passe par cet appel pour les flottants ; deux entiers sont additionnés par le 65C02.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 + Register2
C (llvm-mos)
/* Additionner deux nombres (groupe 4, fonction 0). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
flottant(1, 1.5f); /* registre 1 */
flottant(2, 2.25f); /* registre 2 */
calcul(0); /* Addition */
printf("1.5 + 2.25 = %s\n", en_texte());
return 0;
}1.5 + 2.25 = 3.750000Mad Pascal
// Additionner deux nombres (groupe 4, fonction 0).
program calcul0;
uses crt, neo6502, neo6502math;
var s: string[32];
a: float;
b: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 1.5;
b := 2.25;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(0); // Addition
writeln('1.5 + 2.25 = ', texte);
end.1.5 + 2.25 = 3.750000NeoBASIC
10 ' Additionner deux nombres (groupe 4, fonction 0)
20 print "1.5 + 2.25 = ";1.5 + 2.251.5 + 2.25 = 3.750000Assembleur 65C02 (64tass)
; Additionner deux nombres (groupe 4, fonction 0).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #0 ; fonction 0 : Addition
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $40, $40, $00, $00, $00, $00, $C0, $10, $3F, $40
; registre 1 : 1.5 (flottant), registre 2 : 2.25 (flottant) (types, puis octets entrelacés)
m: .text "1.5 + 2.25 = ", 01.5 + 2.25 = 3.7500004,1 Subtraction Officiel
Registre 1 := registre 1 − registre 2.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | différence |
Un entier et un flottant : le calcul se fait en flottant. En NeoBASIC, - passe par cet appel pour les flottants.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 - Register2
C (llvm-mos)
/* Soustraire deux nombres (groupe 4, fonction 1). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 10); /* registre 1 */
flottant(2, 25.5f); /* registre 2 */
calcul(1); /* Subtraction */
printf("10 - 25.5 = %s\n", en_texte());
return 0;
}10 - 25.5 = -15.500000Mad Pascal
// Soustraire deux nombres (groupe 4, fonction 1).
program calcul1;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 10;
b := 25.5;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(1); // Subtraction
writeln('10 - 25.5 = ', texte);
end.10 - 25.5 = -15.500000NeoBASIC
10 ' Soustraire deux nombres (groupe 4, fonction 1)
20 print "10 - 25.5 = ";10 - 25.510 - 25.5 = -15.500000Assembleur 65C02 (64tass)
; Soustraire deux nombres (groupe 4, fonction 1).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #1 ; fonction 1 : Subtraction
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $40, $0A, $00, $00, $00, $00, $CC, $00, $41
; registre 1 : 10 (entier), registre 2 : 25.5 (flottant) (types, puis octets entrelacés)
m: .text "10 - 25.5 = ", 010 - 25.5 = -15.5000004,2 Multiplication Officiel
Registre 1 := registre 1 × registre 2.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | produit (entier si les deux opérandes le sont) |
Deux entiers donnent un entier 32 bits (sans contrôle de dépassement). En NeoBASIC, * passe toujours par cet appel.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 * Register2
C (llvm-mos)
/* Multiplier deux entiers (groupe 4, fonction 2). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 6); /* registre 1 */
entier(2, 7); /* registre 2 */
calcul(2); /* Multiplication */
printf("6 * 7 = %s\n", en_texte());
return 0;
}6 * 7 = 42Mad Pascal
// Multiplier deux entiers (groupe 4, fonction 2).
program calcul2;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 6;
b := 7;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(2); // Multiplication
writeln('6 * 7 = ', texte);
end.6 * 7 = 42NeoBASIC
10 ' Multiplier deux entiers (groupe 4, fonction 2)
20 print "6 * 7 = ";6 * 76 * 7 = 42Assembleur 65C02 (64tass)
; Multiplier deux entiers (groupe 4, fonction 2).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #2 ; fonction 2 : Multiplication
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $06, $07, $00, $00, $00, $00, $00, $00
; registre 1 : 6 (entier), registre 2 : 7 (entier) (types, puis octets entrelacés)
m: .text "6 * 7 = ", 06 * 7 = 424,3 Decimal Division Officiel
Registre 1 := registre 1 / registre 2, toujours en flottant.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | quotient (flottant) |
erreur | uint8 | 1 si le registre 2 vaut 0 |
Même avec deux entiers, le résultat est flottant. En NeoBASIC, / fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 / Register2 (floating point)
C (llvm-mos)
/* Diviser en flottant (groupe 4, fonction 3). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 7); /* registre 1 */
entier(2, 2); /* registre 2 */
calcul(3); /* Decimal Division */
printf("7 / 2 = %s\n", en_texte());
return 0;
}7 / 2 = 3.500000Mad Pascal
// Diviser en flottant (groupe 4, fonction 3).
program calcul3;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 7;
b := 2;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(3); // Decimal Division
writeln('7 / 2 = ', texte);
end.7 / 2 = 3.500000NeoBASIC
10 ' Diviser en flottant (groupe 4, fonction 3)
20 print "7 / 2 = ";7 / 27 / 2 = 3.500000Assembleur 65C02 (64tass)
; Diviser en flottant (groupe 4, fonction 3).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #3 ; fonction 3 : Decimal Division
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $07, $02, $00, $00, $00, $00, $00, $00
; registre 1 : 7 (entier), registre 2 : 2 (entier) (types, puis octets entrelacés)
m: .text "7 / 2 = ", 07 / 2 = 3.5000004,4 Integer Division Officiel
Registre 1 := registre 1 / registre 2, en entier (quotient tronqué).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | quotient entier |
erreur | uint8 | 1 si le registre 2 vaut 0 |
Des flottants sont d'abord convertis en entiers. En NeoBASIC, \ fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 / Register2 (integer result)
C (llvm-mos)
/* Diviser en entier (groupe 4, fonction 4). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 7); /* registre 1 */
entier(2, 2); /* registre 2 */
calcul(4); /* Integer Division */
printf("7 \\ 2 = %s\n", en_texte());
return 0;
}7 \ 2 = 3Mad Pascal
// Diviser en entier (groupe 4, fonction 4).
program calcul4;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 7;
b := 2;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(4); // Integer Division
writeln('7 \ 2 = ', texte);
end.7 \ 2 = 3NeoBASIC
10 ' Diviser en entier (groupe 4, fonction 4)
20 print "7 \ 2 = ";7 \ 27 \ 2 = 3Assembleur 65C02 (64tass)
; Diviser en entier (groupe 4, fonction 4).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #4 ; fonction 4 : Integer Division
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $07, $02, $00, $00, $00, $00, $00, $00
; registre 1 : 7 (entier), registre 2 : 2 (entier) (types, puis octets entrelacés)
m: .text "7 \ 2 = ", 07 \ 2 = 34,5 Integer Modulus Officiel
Registre 1 := reste de la division entière de registre 1 par registre 2, calculé sur les valeurs absolues.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | reste (toujours positif ou nul) |
erreur | uint8 | 1 si le registre 2 vaut 0 |
Le firmware prend les valeurs absolues des deux opérandes : -17 % 5 donne 2 (et non -2 comme en C). En NeoBASIC, % fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 mod Register2
C (llvm-mos)
/* Reste d'une division entière (groupe 4, fonction 5). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, -17); /* registre 1 */
entier(2, 5); /* registre 2 */
calcul(5); /* Integer Modulus */
printf("-17 %% 5 = %s\n", en_texte());
return 0;
}-17 % 5 = 2Mad Pascal
// Reste d'une division entière (groupe 4, fonction 5).
program calcul5;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := -17;
b := 5;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(5); // Integer Modulus
writeln('-17 % 5 = ', texte);
end.-17 % 5 = 2NeoBASIC
10 ' Reste d'une division entiere (groupe 4, fonction 5)
20 n = -17 : print "-17 % 5 = ";n % 5-17 % 5 = 2Assembleur 65C02 (64tass)
; Reste d'une division entière (groupe 4, fonction 5).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #5 ; fonction 5 : Integer Modulus
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $EF, $05, $FF, $00, $FF, $00, $FF, $00
; registre 1 : -17 (entier), registre 2 : 5 (entier) (types, puis octets entrelacés)
m: .text "-17 % 5 = ", 0-17 % 5 = 24,6 Compare Officiel
Compare registre 1 et registre 2 ; le résultat revient en P0.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | $FF si registre 1 < registre 2, 0 si égaux, 1 si plus grand |
Entre flottants, la comparaison est approchée : deux nombres dont l'écart est inférieur à un dix-millionième de leur taille sont égaux. En NeoBASIC, les comparaisons de flottants (<, =, >…) font cet appel ; celles d'entiers se font sur le 65C02.
Texte de la documentation du firmware (anglais)
Parameter:0 := Register 1 compare Register2 : returns $FF, 0, 1 for less equal and greater. Note: float comparison is approximate because of rounding.
C (llvm-mos)
/* Comparer deux flottants (groupe 4, fonction 6). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
flottant(1, 2.5f); /* registre 1 */
flottant(2, 3.5f); /* registre 2 */
calcul(6); /* Compare */
printf("compare(2.5, 3.5) = %u\n", ControlPort.params[0]); /* $FF : plus petit */
return 0;
}compare(2.5, 3.5) = 255Mad Pascal
// Comparer deux flottants (groupe 4, fonction 6).
program compare;
uses crt, neo6502, neo6502math;
var s: string[32];
a, b: float;
r: byte;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 2.5;
b := 3.5;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(MATHCmp); // Compare
r := NeoMessage.params[0]; // $FF : plus petit
writeln('compare(2.5, 3.5) = ', r);
end.compare(2.5, 3.5) = 255NeoBASIC
10 ' Comparer deux flottants (groupe 4, fonction 6)
20 print "2.5 < 3.5 : ";2.5 < 3.52.5 < 3.5 : -1Assembleur 65C02 (64tass)
; Comparer deux flottants (groupe 4, fonction 6).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #6 ; fonction 6 : Compare
jsr calcul
lda ControlPort+4 ; P0 : $FF, 0 ou 1
pha
lda #<m
ldx #>m
jsr ecrire
pla
jsr decimal
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $40, $40, $00, $00, $00, $00, $20, $60, $40, $40
; registre 1 : 2.5 (flottant), registre 2 : 3.5 (flottant) (types, puis octets entrelacés)
m: .text "compare(2.5, 3.5) = ", 0compare(2.5, 3.5) = 2554,7 Power Officiel
Registre 1 := registre 1 élevé à la puissance registre 2, en flottant.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | puissance (flottant) |
Le résultat est toujours flottant. En NeoBASIC, pow(a, b) fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := Register 1 to the power of Register2 (floating point result whatever)
C (llvm-mos)
/* Élever à une puissance (groupe 4, fonction 7). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 2); /* registre 1 */
entier(2, 10); /* registre 2 */
calcul(7); /* Power */
printf("2 ^ 10 = %s\n", en_texte());
return 0;
}2 ^ 10 = 1024.000000Mad Pascal
// Élever à une puissance (groupe 4, fonction 7).
program calcul7;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 2;
b := 10;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(7); // Power
writeln('2 ^ 10 = ', texte);
end.2 ^ 10 = 1024.000000NeoBASIC
10 ' Élever à une puissance (groupe 4, fonction 7)
20 print "2 ^ 10 = ";pow(2, 10)2 ^ 10 = 1024.000000Assembleur 65C02 (64tass)
; Élever à une puissance (groupe 4, fonction 7).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #7 ; fonction 7 : Power
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $02, $0A, $00, $00, $00, $00, $00, $00
; registre 1 : 2 (entier), registre 2 : 10 (entier) (types, puis octets entrelacés)
m: .text "2 ^ 10 = ", 02 ^ 10 = 1024.0000004,8 Distance (counter-rectangle) Officiel
Registre 1 := racine carrée de (registre 1² + registre 2²) : la distance du point (x, y) à l'origine.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | distance (flottant) |
Pas de mot-clé NeoBASIC : l'exemple BASIC écrit les registres avec poke.
Texte de la documentation du firmware (anglais)
Register1 := Square root of (Register1 * Register1) + (Register2 * Register2)
C (llvm-mos)
/* Distance à l'origine d'un point (groupe 4, fonction 8). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 3); /* registre 1 */
entier(2, 4); /* registre 2 */
calcul(8); /* Distance (counter-rectangle) */
printf("distance(3, 4) = %s\n", en_texte());
return 0;
}distance(3, 4) = 5.000000Mad Pascal
// Distance à l'origine d'un point (groupe 4, fonction 8).
program calcul8;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 3;
b := 4;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(8); // Distance (counter-rectangle)
writeln('distance(3, 4) = ', texte);
end.distance(3, 4) = 5.000000NeoBASIC
10 ' Distance à l'origine d'un point (groupe 4, fonction 8)
20 r = alloc(10) : for i = 0 to 9 : poke r + i, 0 : next i
30 poke r + 2, 3 : poke r + 3, 4 : ' registre 1 : 3, registre 2 : 4 (entiers, pas de 2)
40 while peek($ff00) : wend
50 poke $ff04, r & 255 : poke $ff05, r >> 8 : poke $ff06, 2 : poke $ff01, 8 : poke $ff00, 4
60 while peek($ff00) : wend : t = alloc(34)
70 poke $ff04, r & 255 : poke $ff05, r >> 8 : poke $ff06, 2 : poke $ff08, t & 255 : poke $ff09, t >> 8 : poke $ff01, 34 : poke $ff00, 4
80 while peek($ff00) : wend : b = t : s$ = "" : for i = 1 to peek(b) : s$ = s$ + chr$(peek(b + i)) : next i
90 print "distance(3, 4) = ";s$distance(3, 4) = 5.000000Assembleur 65C02 (64tass)
; Distance à l'origine d'un point (groupe 4, fonction 8).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #8 ; fonction 8 : Distance (counter-rectangle)
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $03, $04, $00, $00, $00, $00, $00, $00
; registre 1 : 3 (entier), registre 2 : 4 (entier) (types, puis octets entrelacés)
m: .text "distance(3, 4) = ", 0distance(3, 4) = 5.0000004,9 Angle calculation (arctangent2) Officiel
Registre 1 := arc tangente de registre 1 / registre 2, dans le bon quadrant : l'angle du point (x = registre 2, y = registre 1).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) ; le registre 2 suit d'un octet |
P2 | uint8 | pas entre les octets d'un registre |
registre 1 | nombre | premier opérande |
registre 2 | nombre | second opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | angle, en degrés ou en radians selon 4,35 |
Le firmware calcule atan2(registre 1, registre 2) : le registre 1 est l'ordonnée. En NeoBASIC, atan2(y, x) fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := arctangent2(Register 1,Register 2) - angle in degrees/radians
C (llvm-mos)
/* Angle d'un point (groupe 4, fonction 9). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 1); /* registre 1 */
entier(2, 1); /* registre 2 */
calcul(9); /* Angle calculation (arctangent2) */
printf("atan2(1, 1) = %s\n", en_texte());
return 0;
}atan2(1, 1) = 45.000000Mad Pascal
// Angle d'un point (groupe 4, fonction 9).
program calcul9;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
NeoWaitMessage;
SetDegreeMode; // Mad Pascal démarre en radians
a := 1;
b := 1;
SetMathStack(a, 0); // position 0 d'abord (voir 4,0)
SetMathStack(b, 1);
calcul(9); // Angle calculation (arctangent2)
writeln('atan2(1, 1) = ', texte);
end.atan2(1, 1) = 45.000000NeoBASIC
10 ' Angle d'un point (groupe 4, fonction 9)
20 print "atan2(1, 1) = ";atan2(1, 1)atan2(1, 1) = 45.000000Assembleur 65C02 (64tass)
; Angle d'un point (groupe 4, fonction 9).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #9 ; fonction 9 : Angle calculation (arctangent2)
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $01, $01, $00, $00, $00, $00, $00, $00
; registre 1 : 1 (entier), registre 2 : 1 (entier) (types, puis octets entrelacés)
m: .text "atan2(1, 1) = ", 0atan2(1, 1) = 45.0000004,16 Negate Officiel
Registre 1 := −registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | opposé, du même type |
En NeoBASIC, le moins unaire fait cet appel pour un flottant ; pour un entier, il n'est pas fait (observé au banc).
Texte de la documentation du firmware (anglais)
Register1 := -Register 1
C (llvm-mos)
/* Changer de signe (groupe 4, fonction 16). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
flottant(1, 2.5f); /* registre 1 */
calcul(16); /* Negate */
printf("-(2.5) = %s\n", en_texte());
return 0;
}-(2.5) = -2.500000Mad Pascal
// Changer de signe (groupe 4, fonction 16).
program calcul16;
uses crt, neo6502, neo6502math;
var s: string[32];
a: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 2.5;
SetMathStack(a, 0);
calcul(16); // Negate
writeln('-(2.5) = ', texte);
end.-(2.5) = -2.500000NeoBASIC
10 ' Changer de signe (groupe 4, fonction 16)
20 n = 2.5 : print "-(2.5) = ";-n-(2.5) = -2.500000Assembleur 65C02 (64tass)
; Changer de signe (groupe 4, fonction 16).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #16 ; fonction 16 : Negate
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $40, $00, $00, $00, $00, $00, $20, $00, $40, $00
; registre 1 : 2.5 (flottant) (types, puis octets entrelacés)
m: .text "-(2.5) = ", 0-(2.5) = -2.5000004,17 Floor Officiel
Registre 1 := plus grand entier inférieur ou égal au registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | entier |
Le résultat est un entier. Le firmware ne convertit que si l'un des deux registres est marqué flottant (il teste les deux types, comme une opération à deux registres). En NeoBASIC, int( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := floor(Register 1)
C (llvm-mos)
/* Partie entière par défaut (groupe 4, fonction 17). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
flottant(1, -3.7f); /* registre 1 */
calcul(17); /* Floor */
printf("floor(-3.7) = %s\n", en_texte());
return 0;
}floor(-3.7) = -4Mad Pascal
// Partie entière par défaut (groupe 4, fonction 17).
program calcul17;
uses crt, neo6502, neo6502math;
var s: string[32];
a: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := -3.7;
SetMathStack(a, 0);
calcul(17); // Floor
writeln('floor(-3.7) = ', texte);
end.floor(-3.7) = -4NeoBASIC
10 ' Partie entiere par defaut (groupe 4, fonction 17)
20 print "floor(-3.7) = ";int(-3.7)floor(-3.7) = -4Assembleur 65C02 (64tass)
; Partie entière par défaut (groupe 4, fonction 17).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #17 ; fonction 17 : Floor
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $40, $00, $CD, $00, $CC, $00, $6C, $00, $C0, $00
; registre 1 : -3.7 (flottant) (types, puis octets entrelacés)
m: .text "floor(-3.7) = ", 0floor(-3.7) = -44,18 Square Root Officiel
Registre 1 := racine carrée du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | racine (flottant) |
erreur | uint8 | 1 si le registre 1 est négatif |
Erreur 1 pour un nombre négatif. En NeoBASIC, sqr( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := square root(Register 1)
C (llvm-mos)
/* Racine carrée (groupe 4, fonction 18). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 2); /* registre 1 */
calcul(18); /* Square Root */
printf("sqrt(2) = %s\n", en_texte());
return 0;
}sqrt(2) = 1.414214Mad Pascal
// Racine carrée (groupe 4, fonction 18).
program calcul18;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 2;
SetMathStack(a, 0);
calcul(18); // Square Root
writeln('sqrt(2) = ', texte);
end.sqrt(2) = 1.414214NeoBASIC
10 ' Racine carree (groupe 4, fonction 18)
20 print "sqrt(2) = ";sqr(2)sqrt(2) = 1.414214Assembleur 65C02 (64tass)
; Racine carrée (groupe 4, fonction 18).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #18 ; fonction 18 : Square Root
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $02, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 2 (entier) (types, puis octets entrelacés)
m: .text "sqrt(2) = ", 0sqrt(2) = 1.4142144,19 Sine Officiel
Registre 1 := sinus du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | sinus (flottant) |
Angle en degrés par défaut, en radians après 4,35 avec P0 = 0. En NeoBASIC, sin( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := sine(Register 1) angles in degrees/radians
C (llvm-mos)
/* Sinus (groupe 4, fonction 19). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 30); /* registre 1 */
calcul(19); /* Sine */
printf("sin(30) = %s\n", en_texte());
return 0;
}sin(30) = 0.500000Mad Pascal
// Sinus (groupe 4, fonction 19).
program calcul19;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
NeoWaitMessage;
SetDegreeMode; // Mad Pascal démarre en radians
a := 30;
SetMathStack(a, 0);
calcul(19); // Sine
writeln('sin(30) = ', texte);
end.sin(30) = 0.500000NeoBASIC
10 ' Sinus (groupe 4, fonction 19)
20 print "sin(30) = ";sin(30)sin(30) = 0.500000Assembleur 65C02 (64tass)
; Sinus (groupe 4, fonction 19).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #19 ; fonction 19 : Sine
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $1E, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 30 (entier) (types, puis octets entrelacés)
m: .text "sin(30) = ", 0sin(30) = 0.5000004,20 Cosine Officiel
Registre 1 := cosinus du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | cosinus (flottant) |
Angle en degrés par défaut (voir 4,35). En NeoBASIC, cos( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := cosine(Register 1) angles in degrees/radians
C (llvm-mos)
/* Cosinus (groupe 4, fonction 20). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 60); /* registre 1 */
calcul(20); /* Cosine */
printf("cos(60) = %s\n", en_texte());
return 0;
}cos(60) = 0.500000Mad Pascal
// Cosinus (groupe 4, fonction 20).
program calcul20;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
NeoWaitMessage;
SetDegreeMode; // Mad Pascal démarre en radians
a := 60;
SetMathStack(a, 0);
calcul(20); // Cosine
writeln('cos(60) = ', texte);
end.cos(60) = 0.500000NeoBASIC
10 ' Cosinus (groupe 4, fonction 20)
20 print "cos(60) = ";cos(60)cos(60) = 0.500000Assembleur 65C02 (64tass)
; Cosinus (groupe 4, fonction 20).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #20 ; fonction 20 : Cosine
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $3C, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 60 (entier) (types, puis octets entrelacés)
m: .text "cos(60) = ", 0cos(60) = 0.5000004,21 Tangent Officiel
Registre 1 := tangente du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | tangente (flottant) |
Angle en degrés par défaut (voir 4,35). En NeoBASIC, tan( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := tangent(Register 1) angles in degrees/radians
C (llvm-mos)
/* Tangente (groupe 4, fonction 21). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 45); /* registre 1 */
calcul(21); /* Tangent */
printf("tan(45) = %s\n", en_texte());
return 0;
}tan(45) = 1.000000Mad Pascal
// Tangente (groupe 4, fonction 21).
program calcul21;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
NeoWaitMessage;
SetDegreeMode; // Mad Pascal démarre en radians
a := 45;
SetMathStack(a, 0);
calcul(21); // Tangent
writeln('tan(45) = ', texte);
end.tan(45) = 1.000000NeoBASIC
10 ' Tangente (groupe 4, fonction 21)
20 print "tan(45) = ";tan(45)tan(45) = 1.000000Assembleur 65C02 (64tass)
; Tangente (groupe 4, fonction 21).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #21 ; fonction 21 : Tangent
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $2D, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 45 (entier) (types, puis octets entrelacés)
m: .text "tan(45) = ", 0tan(45) = 1.0000004,22 Arctangent Officiel
Registre 1 := arc tangente du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | angle (flottant), en degrés ou en radians selon 4,35 |
En NeoBASIC, atan( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := arctangent(Register 1) angles in degrees/radians
C (llvm-mos)
/* Arc tangente (groupe 4, fonction 22). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 1); /* registre 1 */
calcul(22); /* Arctangent */
printf("atan(1) = %s\n", en_texte());
return 0;
}atan(1) = 45.000000Mad Pascal
// Arc tangente (groupe 4, fonction 22).
program calcul22;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
NeoWaitMessage;
SetDegreeMode; // Mad Pascal démarre en radians
a := 1;
SetMathStack(a, 0);
calcul(22); // Arctangent
writeln('atan(1) = ', texte);
end.atan(1) = 45.000000NeoBASIC
10 ' Arc tangente (groupe 4, fonction 22)
20 print "atan(1) = ";atan(1)atan(1) = 45.000000Assembleur 65C02 (64tass)
; Arc tangente (groupe 4, fonction 22).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #22 ; fonction 22 : Arctangent
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $01, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 1 (entier) (types, puis octets entrelacés)
m: .text "atan(1) = ", 0atan(1) = 45.0000004,23 Exponent Officiel
Registre 1 := e puissance registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | exponentielle (flottant) |
En NeoBASIC, exp( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := e to the power of Register 1
C (llvm-mos)
/* Exponentielle (groupe 4, fonction 23). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 1); /* registre 1 */
calcul(23); /* Exponent */
printf("exp(1) = %s\n", en_texte());
return 0;
}exp(1) = 2.718282Mad Pascal
// Exponentielle (groupe 4, fonction 23).
program calcul23;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 1;
SetMathStack(a, 0);
calcul(23); // Exponent
writeln('exp(1) = ', texte);
end.exp(1) = 2.718282NeoBASIC
10 ' Exponentielle (groupe 4, fonction 23)
20 print "exp(1) = ";exp(1)exp(1) = 2.718282Assembleur 65C02 (64tass)
; Exponentielle (groupe 4, fonction 23).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #23 ; fonction 23 : Exponent
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $01, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 1 (entier) (types, puis octets entrelacés)
m: .text "exp(1) = ", 0exp(1) = 2.7182824,24 Logarithm Officiel
Registre 1 := logarithme népérien du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | logarithme (flottant) |
erreur | uint8 | 1 si le registre 1 est négatif |
Erreur 1 pour un nombre négatif. En NeoBASIC, log( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := log(Register 1) natural logarithm
C (llvm-mos)
/* Logarithme népérien (groupe 4, fonction 24). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 10); /* registre 1 */
calcul(24); /* Logarithm */
printf("log(10) = %s\n", en_texte());
return 0;
}log(10) = 2.302585Mad Pascal
// Logarithme népérien (groupe 4, fonction 24).
program calcul24;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 10;
SetMathStack(a, 0);
calcul(24); // Logarithm
writeln('log(10) = ', texte);
end.log(10) = 2.302585NeoBASIC
10 ' Logarithme neperien (groupe 4, fonction 24)
20 print "log(10) = ";log(10)log(10) = 2.302585Assembleur 65C02 (64tass)
; Logarithme népérien (groupe 4, fonction 24).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #24 ; fonction 24 : Logarithm
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $0A, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 10 (entier) (types, puis octets entrelacés)
m: .text "log(10) = ", 0log(10) = 2.3025854,25 Absolute Value Officiel
Registre 1 := valeur absolue du registre 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | valeur absolue, du même type |
En NeoBASIC, abs( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := absolute value(Register 1)
C (llvm-mos)
/* Valeur absolue (groupe 4, fonction 25). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
flottant(1, -7.25f); /* registre 1 */
calcul(25); /* Absolute Value */
printf("abs(-7.25) = %s\n", en_texte());
return 0;
}abs(-7.25) = 7.250000Mad Pascal
// Valeur absolue (groupe 4, fonction 25).
program calcul25;
uses crt, neo6502, neo6502math;
var s: string[32];
a: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := -7.25;
SetMathStack(a, 0);
calcul(25); // Absolute Value
writeln('abs(-7.25) = ', texte);
end.abs(-7.25) = 7.250000NeoBASIC
10 ' Valeur absolue (groupe 4, fonction 25)
20 print "abs(-7.25) = ";abs(-7.25)abs(-7.25) = 7.250000Assembleur 65C02 (64tass)
; Valeur absolue (groupe 4, fonction 25).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #25 ; fonction 25 : Absolute Value
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $40, $00, $00, $00, $00, $00, $E8, $00, $C0, $00
; registre 1 : -7.25 (flottant) (types, puis octets entrelacés)
m: .text "abs(-7.25) = ", 0abs(-7.25) = 7.2500004,26 Sign Officiel
Registre 1 := signe du registre 1 : −1, 0 ou 1.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | −1, 0 ou 1 (entier) |
En NeoBASIC, sgn( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := sign(Register 1), returns -1 0 or 1
C (llvm-mos)
/* Signe (groupe 4, fonction 26). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
flottant(1, -3.5f); /* registre 1 */
calcul(26); /* Sign */
printf("sgn(-3.5) = %s\n", en_texte());
return 0;
}sgn(-3.5) = -1Mad Pascal
// Signe (groupe 4, fonction 26).
program calcul26;
uses crt, neo6502, neo6502math;
var s: string[32];
a: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := -3.5;
SetMathStack(a, 0);
calcul(26); // Sign
writeln('sgn(-3.5) = ', texte);
end.sgn(-3.5) = -1NeoBASIC
10 ' Signe (groupe 4, fonction 26)
20 print "sgn(-3.5) = ";sgn(-3.5)sgn(-3.5) = -1Assembleur 65C02 (64tass)
; Signe (groupe 4, fonction 26).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #26 ; fonction 26 : Sign
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $40, $00, $00, $00, $00, $00, $60, $00, $C0, $00
; registre 1 : -3.5 (flottant) (types, puis octets entrelacés)
m: .text "sgn(-3.5) = ", 0sgn(-3.5) = -14,27 Random Decimal Officiel
Registre 1 := nombre au hasard entre 0 (compris) et 1 (exclu).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | nombre au hasard (flottant) |
Le firmware tire un entier de 0 à 31999 et le divise par 32000 : 32000 valeurs possibles. En NeoBASIC, rnd( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := random float from 0-1
C (llvm-mos)
/* Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
calcul(27); /* Random Decimal */
printf("Hasard : %s\n", en_texte());
return 0;
}Hasard : 0.043219Mad Pascal
// Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27).
program hasard;
uses crt, neo6502, neo6502math;
var s: string[32];
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
calcul(MATHFRnd); // Random Decimal
writeln('Hasard : ', texte);
end.Hasard : 0.043219NeoBASIC
10 ' Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27)
20 print "Hasard : ";rnd(1)Hasard : 0.043219Assembleur 65C02 (64tass)
; Tirer un nombre au hasard entre 0 et 1 (groupe 4, fonction 27).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #27 ; fonction 27 : Random Decimal
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .fill 10
m: .text "Hasard : ", 0Hasard : 0.0432194,28 Random Integer Officiel
Registre 1 := entier au hasard de 0 à (registre 1 − 1).
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | entier au hasard |
Si le registre 1 vaut 0 ou moins, il reste inchangé. En NeoBASIC, rand( fait cet appel.
Texte de la documentation du firmware (anglais)
Register1 := random integer from 0 to (Register 1-1)
C (llvm-mos)
/* Lancer un dé à 6 faces (groupe 4, fonction 28). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, 6); /* registre 1 */
calcul(28); /* Random Integer */
printf("Tirage de 0 a 5 : %s\n", en_texte());
return 0;
}Tirage de 0 a 5 : 1Mad Pascal
// Lancer un dé à 6 faces (groupe 4, fonction 28).
program calcul28;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 6;
SetMathStack(a, 0);
calcul(28); // Random Integer
writeln('Tirage de 0 a 5 : ', texte);
end.Tirage de 0 a 5 : 1NeoBASIC
10 ' Lancer un de à 6 faces (groupe 4, fonction 28)
20 print "Tirage de 0 a 5 : ";rand(6)Tirage de 0 a 5 : 1Assembleur 65C02 (64tass)
; Lancer un dé à 6 faces (groupe 4, fonction 28).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: ldx #28 ; fonction 28 : Random Integer
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $06, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 6 (entier) (types, puis octets entrelacés)
m: .text "Tirage de 0 a 5 : ", 0Tirage de 0 a 5 : 14,32 Number to Decimal Officiel
Ajoute au registre 1 une partie décimale donnée en chiffres BCD : c'est l'outil du tokeniseur de NeoBASIC pour les constantes décimales.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | partie entière |
P4-P5 | addr | adresse des chiffres après la virgule, deux par octet (BCD), terminés par un quartet $F |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | registre 1 + 0,chiffres (flottant) |
La documentation du firmware dit de ne pas l'utiliser : c'est un outil interne de NeoBASIC, qui l'appelle pour chaque constante décimale d'un programme (1.5, 3.14…). L'unité neo6502math de Mad Pascal l'enveloppe dans AddFractionalBCD. Exemple : 3 et les chiffres 1 4 1 5 9 ($14 $15 $9F) donnent 3,14159.
Texte de la documentation du firmware (anglais)
Helper function for tokeniser, do not use.
C (llvm-mos)
/* Ajouter une partie décimale en BCD (groupe 4, fonction 32). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
static const uint8_t chiffres[] = { 0x14, 0x15, 0x9F }; /* 1 4 1 5 9, fin : $F */
int main(void) {
entier(1, 3); /* registre 1 : partie entière */
ControlPort.params[4] = (uint16_t)chiffres & 0xFF; /* P4-P5 : chiffres */
ControlPort.params[5] = (uint16_t)chiffres >> 8;
calcul(32); /* Number to Decimal */
printf("3 + 0,14159 = %s\n", en_texte());
return 0;
}3 + 0,14159 = 3.141590Mad Pascal
// Ajouter une partie décimale en BCD (groupe 4, fonction 32).
program decimales;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
chiffres: array[0..2] of byte = ($14, $15, $9F); // 1 4 1 5 9, fin : $F
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := 3;
SetMathStack(a, 0); // registre 1 : partie entière
wordParams[2] := word(@chiffres); // P4-P5 : chiffres
calcul(MATHProcessDecimal); // Number to Decimal
writeln('3 + 0,14159 = ', texte);
end.3 + 0,14159 = 3.141590NeoBASIC
10 ' Ajouter une partie decimale en BCD (groupe 4, fonction 32)
20 ' NeoBASIC fait cet appel pour chaque constante decimale, ici 3.14159
30 print "3 + 0,14159 = ";3.141593 + 0,14159 = 3.141590Assembleur 65C02 (64tass)
; Ajouter une partie décimale en BCD (groupe 4, fonction 32).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<chiffres
sta ControlPort+8 ; P4-P5 : chiffres
lda #>chiffres
sta ControlPort+9
ldx #32 ; fonction 32 : Number to Decimal
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jmp WriteCharacter
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $03, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 3 (entier) (types, puis octets entrelacés)
chiffres: .byte $14, $15, $9F ; 1 4 1 5 9, fin : $F
m: .text "3 + 0,14159 = ", 03 + 0,14159 = 3.1415904,33 String to Number Officiel
Convertit un texte en nombre dans le registre 1 : entier s'il n'a pas de partie décimale, flottant sinon.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
P4-P5 | addr | adresse du texte (précédé de sa longueur) |
| Octets | Type | Rôle |
|---|---|---|
registre 1 | nombre | nombre |
erreur | uint8 | 1 si le texte n'est pas un nombre |
L'exemple convertit « 2.5 » puis affiche le type obtenu ($40 : flottant). En NeoBASIC, val( fait cet appel, de même que input pour un nombre. L'unité neo6502math de Mad Pascal l'utilise dans NeoParseInt et NeoParseFloat.
Texte de la documentation du firmware (anglais)
Convert the length prefixed string at Parameters:4,5 to a constant in Register1.
C (llvm-mos)
/* Convertir un texte en nombre (groupe 4, fonction 33). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
static const uint8_t nombre[] = "\x03" "2.5";
int main(void) {
ControlPort.params[4] = (uint16_t)nombre & 0xFF; /* P4-P5 : texte */
ControlPort.params[5] = (uint16_t)nombre >> 8;
calcul(33); /* String to Number */
uint8_t type = reg[0]; /* $40 : flottant */
printf("\"2.5\" -> %s (type %u)\n", en_texte(), type);
return 0;
}"2.5" -> 2.500000 (type 64)Mad Pascal
// Convertir un texte en nombre (groupe 4, fonction 33).
program valeur;
uses crt, neo6502, neo6502math;
var s: string[32];
nombre: string[8];
t: byte;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
nombre := '2.5';
wordParams[2] := word(@nombre); // P4-P5 : texte
calcul(MATHConvertStringToNumber); // String to Number
t := peek($F5); // type du registre 1 : $40, flottant
writeln('"2.5" -> ', texte, ' (type ', t, ')');
end."2.5" -> 2.500000 (type 64)NeoBASIC
10 ' Convertir un texte en nombre (groupe 4, fonction 33)
20 print chr$(34);"2.5";chr$(34);" -> ";val("2.5")"2.5" -> 2.500000Assembleur 65C02 (64tass)
; Convertir un texte en nombre (groupe 4, fonction 33).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<nombre
sta ControlPort+8 ; P4-P5 : texte
lda #>nombre
sta ControlPort+9
ldx #33 ; fonction 33 : String to Number
jsr calcul
lda reg ; type du registre 1 : $40, flottant
sta type
lda #<m1
ldx #>m1
jsr ecrire
jsr affiche
lda #<m2
ldx #>m2
jsr ecrire
lda type
jsr decimal
lda #<m3
ldx #>m3
jmp ecrire
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .fill 10
nombre: .byte 3
.text "2.5"
type: .byte 0
m1: .text '"2.5" -> ', 0
m2: .text " (type ", 0
m3: .text ")", 13, 0"2.5" -> 2.500000 (type 64)4,34 Number to String Officiel
Convertit le registre 1 en texte (précédé de sa longueur) : entier en décimal, flottant avec 6 décimales.
| Octets | Type | Rôle |
|---|---|---|
P0-P1 | addr | adresse du registre 1 (octet de type) |
P2 | uint8 | pas entre les octets du registre |
registre 1 | nombre | opérande |
P4-P5 | addr | adresse du tampon du texte |
| Octets | Type | Rôle |
|---|---|---|
tampon | string | texte (précédé de sa longueur) |
Format du C : %d pour un entier, %f pour un flottant (0.250000). Sur Trinity, l'écriture est bornée à la fin de la mémoire du 65C02 (T-59) ; le firmware officiel écrit autant de caractères que le nombre en demande. NeoBASIC fait cet appel pour afficher un nombre (print) et dans str$(.
Texte de la documentation du firmware (anglais)
Convert the constant in Register1 to a length prefixed string which is stored at Parameters:4,5
C (llvm-mos)
/* Convertir des nombres en texte (groupe 4, fonction 34). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
int main(void) {
entier(1, -123);
printf("-123 -> \"%s\"\n", en_texte()); /* en_texte : Number to String */
flottant(1, 0.25f);
printf("0.25 -> \"%s\"\n", en_texte());
return 0;
}-123 -> "-123"
0.25 -> "0.250000"Mad Pascal
// Convertir des nombres en texte (groupe 4, fonction 34).
program texte34;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
b: float;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
a := -123;
SetMathStack(a, 0);
writeln('-123 -> "', texte, '"'); // texte : Number to String
b := 0.25;
SetMathStack(b, 0);
writeln('0.25 -> "', texte, '"');
end.-123 -> "-123"
0.25 -> "0.250000"NeoBASIC
10 ' Convertir des nombres en texte (groupe 4, fonction 34)
20 print "-123 -> ";chr$(34);str$(-123);chr$(34)
30 print "0.25 -> ";chr$(34);str$(0.25);chr$(34)-123 -> "-123"
0.25 -> "0.250000"Assembleur 65C02 (64tass)
; Convertir des nombres en texte (groupe 4, fonction 34).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<m1
ldx #>m1
jsr ecrire
jsr affiche ; affiche : fonction 34, Number to String
lda #<m2
ldx #>m2
jsr ecrire
ldx #9
_copie: lda quart,x ; registre 1 := 0.25
sta reg,x
dex
bpl _copie
lda #<m3
ldx #>m3
jsr ecrire
jsr affiche
lda #<m2
ldx #>m2
jmp ecrire
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $85, $00, $FF, $00, $FF, $00, $FF, $00
; registre 1 : -123 (entier) (types, puis octets entrelacés)
quart: .byte $40, $00, $00, $00, $00, $00, $80, $00, $3E, $00
; registre 1 : 0.25 (flottant) (types, puis octets entrelacés)
m1: .text '-123 -> "', 0
m2: .text '"', 13, 0
m3: .text '0.25 -> "', 0-123 -> "-123"
0.25 -> "0.250000"4,35 Set Degree/Radian Mode Officiel
Choisit l'unité des angles des fonctions 9, 19 à 22 : degrés (défaut) ou radians.
| Octets | Type | Rôle |
|---|---|---|
P0 | uint8 | non nul : degrés ; 0 : radians |
Sorties : aucune.
Le réglage vaut pour tous les programmes jusqu'au prochain appel. Le code de démarrage de Mad Pascal 1.7.8 passe en radians ; ses routines SetDegreeMode et SetRadianMode font cet appel. En NeoBASIC, clear (et donc run) remet les degrés. L'exemple passe en radians, calcule atan(1) = π/4, puis revient aux degrés.
Mots-clés NeoBASIC qui font cet appel : clear
Texte de la documentation du firmware (anglais)
Sets the use of degrees (the default) when non zero, radians when zero.
C (llvm-mos)
/* Calculer en radians, puis revenir aux degrés (groupe 4, fonction 35). */
#include <stdio.h>
#include <neo6502.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t reg[10]; /* registres 1 et 2 entrelacés, pas de 2 */
static char texte[34];
static void entier(uint8_t r, int32_t v) { /* registre r (1 ou 2) := entier v */
reg[r - 1] = 0x00;
for (uint8_t i = 0; i < 4; i++)
reg[r + 1 + 2 * i] = (uint8_t)(v >> (8 * i));
}
static void flottant(uint8_t r, float v) { /* registre r := flottant v */
union { float f; int32_t i; } u;
u.f = v;
entier(r, u.i);
reg[r - 1] = 0x40;
}
static void calcul(uint8_t fonction) { /* appel du groupe 4 sur les registres */
libre();
ControlPort.params[0] = (uint16_t)reg & 0xFF;
ControlPort.params[1] = (uint16_t)reg >> 8;
ControlPort.params[2] = 2; /* pas */
api(4, fonction);
}
static const char *en_texte(void) { /* registre 1 en texte, par 4,34 */
ControlPort.params[4] = (uint16_t)texte & 0xFF;
ControlPort.params[5] = (uint16_t)texte >> 8;
calcul(34);
texte[(uint8_t)texte[0] + 1] = 0;
return texte + 1;
}
static void mode(uint8_t degres) {
libre();
ControlPort.params[0] = degres; /* P0 : 0 radians, sinon degrés */
api(4, 35); /* Set Degree/Radian Mode */
}
int main(void) {
mode(0);
entier(1, 1);
calcul(22); /* 4,22 : arc tangente */
printf("atan(1) en radians = %s\n", en_texte());
mode(1);
return 0;
}atan(1) en radians = 0.785398Mad Pascal
// Calculer en radians, puis revenir aux degrés (groupe 4, fonction 35).
program radians;
uses crt, neo6502, neo6502math;
var s: string[32];
a: integer;
procedure calcul(f: byte); // appel du groupe 4 sur la pile ($F5, pas de 2)
begin
DoMathOnStack(f);
NeoWaitMessage; // attendre le résultat
end;
function texte: string; // registre 1 en texte, par 4,34
begin
wordParams[2] := word(@s); // P4-P5 : tampon
calcul(MATHConvertNumberToString);
result := s;
end;
begin
NeoWaitMessage;
SetRadianMode; // Set Degree/Radian Mode, P0 = 0
a := 1;
SetMathStack(a, 0);
calcul(MATHATan); // 4,22 : arc tangente
writeln('atan(1) en radians = ', texte);
NeoWaitMessage;
SetDegreeMode; // P0 = 1
NeoWaitMessage;
end.atan(1) en radians = 0.785398NeoBASIC
10 ' Calculer en radians, puis revenir aux degres (groupe 4, fonction 35)
20 while peek($ff00) : wend
30 poke $ff04, 0 : poke $ff01, 35 : poke $ff00, 4 : ' radians
40 while peek($ff00) : wend
50 print "atan(1) en radians = ";atan(1)
60 while peek($ff00) : wend
70 poke $ff04, 1 : poke $ff01, 35 : poke $ff00, 4 : ' degres
80 while peek($ff00) : wendatan(1) en radians = 0.785398Assembleur 65C02 (64tass)
; Calculer en radians, puis revenir aux degrés (groupe 4, fonction 35).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #0
jsr mode ; radians
ldx #22 ; 4,22 : arc tangente
jsr calcul
lda #<m
ldx #>m
jsr ecrire
jsr affiche
lda #13
jsr WriteCharacter
lda #1 ; retour aux degrés
mode: pha
jsr WaitMessage
pla
sta ControlPort+4 ; P0 : 0 radians, sinon degrés
lda #4
ldx #35 ; fonction 35 : Set Degree/Radian Mode
jmp appel
; Appel du groupe 4, fonction X, sur les registres de reg (pas de 2).
calcul: jsr WaitMessage
lda #<reg
sta ControlPort+4 ; P0-P1 : registre 1
lda #>reg
sta ControlPort+5
lda #2
sta ControlPort+6 ; P2 : pas
lda #4
jmp appel
; Affiche le registre 1, converti en texte par 4,34.
affiche:
jsr WaitMessage
lda #<texte
sta ControlPort+8 ; P4-P5 : tampon
lda #>texte
sta ControlPort+9
ldx #34
jsr calcul
lda #<texte
ldx #>texte
jmp pecrire
texte: .fill 34
; Affiche la chaîne précédée de sa longueur dont l'adresse est dans A (poids faible) et X (poids fort).
pecrire:
sta ptr
stx ptr+1
lda (ptr)
sta reste
ldy #1
_p: lda reste
beq _pf
lda (ptr),y
jsr WriteCharacter
iny
dec reste
bra _p
_pf: rts
reste: .byte 0
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
diviseur: .byte 0
reg: .byte $00, $00, $01, $00, $00, $00, $00, $00, $00, $00
; registre 1 : 1 (entier) (types, puis octets entrelacés)
m: .text "atan(1) en radians = ", 0atan(1) en radians = 0.785398