{"id":1231,"date":"2025-11-25T19:26:02","date_gmt":"2025-11-25T19:26:02","guid":{"rendered":"https:\/\/ve2cuy.com\/blog\/?page_id=1231"},"modified":"2025-11-25T19:28:46","modified_gmt":"2025-11-25T19:28:46","slug":"trs-80-assembleur","status":"publish","type":"page","link":"https:\/\/ve2cuy.com\/blog\/index.php\/trs-80-assembleur\/","title":{"rendered":"TRS-80 : Assembleur"},"content":{"rendered":"\n<ul class=\"wp-block-list\">\n<li>Compilation, \u00e0 partir de Windows d&rsquo;un programme Z80 (<a href=\"http:\/\/48k.ca\/zmac.html\">zmac<\/a>):<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">zmac file_name<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tester un programme \u00e0 partir d&rsquo;un \u00e9mulateur (<a href=\"http:\/\/48k.ca\/trs80gp.html\">trs80gp<\/a>):<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">trs80gp -ld -m3 -vs zout\/file_name ; -ld = LDOS, -vs = Sharp Display<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Les outils de d\u00e9veloppement sont dans <\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Z:\\0 - Documentation\\R\u00e9seau et \u00e9quipement maison\\TRS-80\\ASM-Tool-Chain&amp;gt;<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Outils images disque<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/sourceforge.net\/projects\/imdisk-toolkit\/\"><\/a><a href=\"https:\/\/www.trs-80.com\/wordpress\/emulators\/disk-utilities\/\">Virtual Disk Utilities \u2013 Ira Goldklang&rsquo;s TRS-80 Revived Site<\/a> (<strong>TRSTools<\/strong>)<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pour le <strong>TRS-80 mod\u00e8le 2<\/strong>:<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Les fichiers images de type <strong>IMD <\/strong>doivent \u00eatre convertis en format <strong>HFE <\/strong>avec l&rsquo;application <strong><a href=\"https:\/\/hxc2001.com\/download\/floppy_drive_emulator\/HxCFloppyEmulator_soft.zip\">HxCFloppyEmulator<\/a><\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Exemple d&rsquo;un programme &#8211; Hello World &#8211; utilisant des appels de LDOS:<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">; zmac file_name\n; trs80gp -ld -m3 -vs zout\/file_name ; -ld = LDOS, -vs = Sharp Display\n        ORG     7000H\n\n@DSPLY  EQU     4467H  ;LDOS 5.1\/MOD3 - pg 6-66 \n@EXIT   EQU     402DH  ;pg 6-60\n@KEY    EQU     0049H  ; \n@TIME   EQU     3036H  ;446DH ; 3036H  PG 6-58\n@DATE   EQU     3033H\n\nVIDEO   EQU     3C00H\nVSIZE   EQU     1024\nENTER   EQU     0DH\nTEXT    DEFB    'TIME AND DATE VIA SYS-CALL @TIME, @DATE', ENTER\nBUFFER  DEFB    '        ', ENTER\nMAIN:\n\n        LD      DE,VSIZE\n        LD      HL, VIDEO\nLOOP:\n        LD      A,'X'\n        LD      (HL),A\n        INC     HL\n        DEC     DE\n        LD      A,D\n        OR      E\n        JP      NZ,LOOP\n        CALL    @KEY        ; WAIT UNTIL KEY PRESSED\n        LD      HL,TEXT\n        CALL    @DSPLY\n\n; GET TIME AND DISPLAY IT\n        LD      HL,BUFFER\n        CALL    @TIME\n        LD      HL,BUFFER\n        CALL    @DSPLY\n\n; GET DATE AND DISPLAY IT\n        LD      HL,BUFFER\n        CALL    @DATE\n        LD      HL,BUFFER\n        CALL    @DSPLY\n\n        CALL    @KEY        ; WAIT UNTIL KEY PRESSED\n        CALL    @EXIT\n        END     MAIN<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">Un autre exemple &#8211; Compter jusqu&rsquo;\u00e0 0xFFFF<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">; Auteur: Alain Boudreault (VE2CUY)\n; Date: 2025.08.10\n; Description: Compter de 0 \u00e0 255 et afficher en DEC et de 0 \u00e0 0xFFFF en HEX\n; Assembleur: zmac\n; Emulateur: trs80gp\n; --------------------------------------------------------------------------\n; zmac file_name\n; trs80gp -ld -m3 -vs zout\/file_name ; -ld = LDOS, -vs = Sharp Display\n; --------------------------------------------------------------------------\n\n                ORG     7000H\n\n@DSPLY          EQU     4467H  ;LDOS 5.1\/MOD3 - pg 6-66 \n@EXIT           EQU     402DH  ;pg 6-60\n@KEY            EQU     0049H  ; \n@TIME           EQU     3036H  ;446DH ; 3036H  PG 6-58\n@DATE           EQU     3033H\n\nVIDEO           EQU     3C00H\nVSIZE           EQU     1024\nENTER           EQU     0DH\nLINE_FEED       EQU     0AH\nAUTEUR          DEFB    LINE_FEED \n                DEFB    '---------------------------------------------------',          LINE_FEED\n                DEFB    'Programme: counter\/cmd, par VE2CUY 2025.08.20',                LINE_FEED\n                DEFB    'Ce programme utilise des sous-routines de LDOS 5.1',           LINE_FEED\n                DEFB    '---------------------------------------------------',          ENTER\n\nMSG1            \n                DEFB    'Compter de 0 a 255 en DEC, Enter pour commencer ...',          ENTER\n\nMSG2            DEFB    LINE_FEED, LINE_FEED\n                DEFB    '---------------------------------------------------',          LINE_FEED  \n                DEFB    'Compter de 0 a 0xFFFF en HEX, Enter pour commencer:',          LINE_FEED\n                DEFB    '---------------------------------------------------',          ENTER\nBUFFER          DEFB    '        ', ENTER\nTEXTE           DEFS    7       ; Buffer for number string'\n\n; ---------------------------------------------------------------------\nMAIN:\n        LD      HL,AUTEUR\n        CALL    @DSPLY        \n        LD      HL,MSG1\n        CALL    @DSPLY\n        CALL    @KEY            ; WAIT UNTIL KEY PRESSED\n       \n; Afficher les nombres de 0 \u00e0 255\nStart:\n        LD      IX, 0           ; IX = compteur de 0 \u00e0 255\nboucle:\n        LD      A, IXl          ; Charger la valeur du compteur dans A\n        LD      HL,TEXTE\n        CALL    NumberToString  ; Convert number in A to string at HL\n        LD      HL,TEXTE        ; Now HL points to the end of the string, we need to backtrack to the start\n        CALL    @DSPLY          ; Display the string\n        INC     IX\n        LD      A, IXl\n        CP      0               ; quand IXl revient \u00e0 0, on a atteint 256\n        JR      NZ, boucle\n; ### FIN de : ; Afficher les nombres de 0 \u00e0 255\n\n; Afficher les nombres de 0 \u00e0 0xFFFF en HEX\n        LD      HL,MSG2\n        CALL    @DSPLY\n        CALL    @KEY            ; WAIT UNTIL KEY PRESSED\n        LD      IX, 0           ; IX = compteur de 0 \u00e0 255\n        LD      DE, 0\n\nboucle2:\n        LD      HL,TEXTE\n        CALL    NumberToHex     ; Convert number in DE to string at HL\n        PUSH    DE              ; ATTENTION, @DSPLY va modifier DE\n        LD      HL,TEXTE        ; Now HL points to the end of the string, we need to backtrack to the start\n        CALL    @DSPLY          ; Display the string\n        POP     DE\n        INC     DE\n        INC     IX\n                                ; V\u00e9rifier si IX == 0\n                                ; Le Z80 ne permet pas de faire CP IX, 0 directement car \n                                ; il ne supporte pas les comparaisons 16 bits avec un imm\u00e9diat.\n                                ; Il faut comparer chaque partie s\u00e9par\u00e9ment.\n        LD A, IXH\n        OR IXL                  ; combine les deux : A sera 0 seulement si les deux sont 0\n        CP 0                    ; pas n\u00e9cessaire, mais explicite\n        JR      NZ, boucle2\n; ### FIN de : ; Afficher les nombres de 0x0 \u00e0 0xFFFF\n\n        CALL    @EXIT           ; Quitter le programme - Retour \u00e0 LDOS\n\n;---------------------------------------------------------------------\n; #### Mes fonctions!\n;---------------------------------------------------------------------\n; Sous-routine : NumberToString\n; Entr\u00e9e : A contient le nombre (0-255)\n;          HL contient l'adresse du tampon de sortie\n; Sortie : [HL] contient la cha\u00eene ASCII termin\u00e9e par z\u00e9ro\n\nNumberToString:\n    LD B, 0                     ; B = nombre de chiffres extraits\n    LD C, A                     ; C = copie du nombre original\n\n    ; Extraire les centaines\n    LD A, C\n    LD D, 0\nHundredsLoop:\n    CP 100\n    JR C, SkipHundreds\n    SUB 100\n    INC D\n    JR HundredsLoop\nSkipHundreds:\n    LD C, A                     ; C = reste apr\u00e8s centaines\n    LD A, D\n    CALL AddDigitToBuffer\n    INC B                       ; un chiffre extrait\n\n    ; Extraire les dizaines\n    LD A, C\n    LD D, 0\nTensLoop:\n    CP 10\n    JR C, SkipTens\n    SUB 10\n    INC D\n    JR TensLoop\nSkipTens:\n    LD C, A                     ; C = unit\u00e9s\n    LD A, D\n    CALL AddDigitToBuffer\n    INC B\n\n    ; Extraire les unit\u00e9s\n    LD A, C\n    CALL AddDigitToBuffer\n    INC B\n\n    ; Terminer la cha\u00eene par CR\/LF\n    LD (HL), ENTER\n    RET\n\n;------------------------------------\n; Sous-routine : AddDigitToBuffer\n; Entr\u00e9e : A contient un chiffre (0-9)\n;          HL pointe vers l\u2019endroit o\u00f9 \u00e9crire\n; Sortie : \u00e9crit le chiffre converti en ASCII \u00e0 (HL) et incr\u00e9mente HL\nAddDigitToBuffer:\n    ADD A, '0'                  ; Convertir en ASCII\n    LD (HL), A\n    INC HL\n    RET\n\n\n;------------------------------------------------------------  \n; Sous-routine : NumberToHex\n; Convertir un nombre en HEX.\n; Entr\u00e9e : DE contient un nombre\n;          HL pointe vers l\u2019endroit o\u00f9 \u00e9crire\n; Sortie : \u00e9crit le chiffre converti en ASCII \u00e0 (HL) et incr\u00e9mente HL\n;\nNumberToHex:\n   ; show \"0x\" as a prefix\n   ld a, '0'\n   LD (HL), A\n   INC HL\n   ld a, 'x'\n   LD (HL), A\n   INC HL\n   ; Store the high-value\n   ld  c,d\n   call  OutHex8\n\n   ; Store the low-value\n   ld  c,e\n   call OutHex8\n   LD (HL), ENTER\n   ; Return to our caller\n   ret\n\n;\n; Output the hex value of the 8-bit number stored in C\n;\nOutHex8:\n   ld  a,c\n   rra\n   rra\n   rra\n   rra\n   call  Conv\n   ld  a,c\nConv:\n   and  $0F\n   add  a,$90\n   daa\n   adc  a,$40\n   daa\n   ; Store the value.\n   LD (HL), A\n   INC HL\n   ret\n\n;---------------------------------------------------------------------\n; FIN du programme\n;---------------------------------------------------------------------\n        END     MAIN<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Afficher sans OS<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">; ----------------------------------------------------  \n; Fichier:  Projets\/afficher.asm\n; Auteur:   Alain Boudreault\n; Date:     2025.08.12 - Soir\u00e9e des perc\u00e9ides\n; Cible:    TRS-80 mod\u00e8le 3\n; ----------------------------------------------------\n; Description: Afficher \u00e0 l'\u00e9cran sans utiliser les\n;              appels syst\u00e8me de LDOS 5.1\/MOD3.\n; ----------------------------------------------------  \n\n            ORG     7000H\n\nVIDEO       EQU     3C00H\nVSIZE       EQU     1024\nTITRE       DEFB    'Ce menu ne sert absolument a rien', 0\nLIGNE       DEFB    '---------------------------------', 0\nMENU01      DEFB    '1. Manger des pommes', 0\nMENU02      DEFB    '2. Activer la manivelle', 0\nMENU03      DEFB    '3. Courir plus vite', 0\nMENU04      DEFB    '4. Esperer mieux', 0\nMENU99      DEFB    'Faites votre choix: _', 0\n\nMAIN:\n    CALL    CLEAR_SCREEN        ; Efface l'\u00e9cran\n    CALL    DISPLAY_MENU        ; Affiche le menu\nYO:\n    JP      YO                  ; Boucle infinie\n\n\n; -----------------------------------------------------------------\nDISPLAY_MENU:\n    LD      DE, TITRE           ; Affiche le titre\n    LD      B, 0                ; Ligne\n    LD      C, 0                ; Colonne\n    CALL    DISPLAY_ZSTRING\n    INC     B                   ; Passe \u00e0 la ligne suivante   \n    LD      DE, LIGNE           ; Affiche la ligne de s\u00e9paration\n    CALL    DISPLAY_ZSTRING    \n    INC     B                   ; Passe \u00e0 la ligne suivante   \n    LD      DE, MENU01          ; Affiche le menu\n    CALL    DISPLAY_ZSTRING\n    INC     B                   ; Passe \u00e0 la ligne suivante\n    LD      DE, MENU02\n    CALL    DISPLAY_ZSTRING\n    INC     B                   ; Passe \u00e0 la ligne suivante\n    LD      DE, MENU03\n    CALL    DISPLAY_ZSTRING\n    INC     B                   ; Passe \u00e0 la ligne suivante\n    LD      DE, MENU04\n    CALL    DISPLAY_ZSTRING\n    INC     B                   ; Passe \u00e0 la ligne suivante   \n    LD      DE, LIGNE           ; Affiche la ligne de s\u00e9paration\n    CALL    DISPLAY_ZSTRING           \n    INC     B                   ; Sauter deux lignes  - Pas possible de faire ADD B,2  ;-)\n    INC     B                   \n    LD      DE, MENU99\n    CALL    DISPLAY_ZSTRING       \n    RET\n\n\n; -----------------------------------------------------------------\n; Affiche une cha\u00eene termin\u00e9e par 0 \u00e0 une position (ligne, colonne)\n; Entr\u00e9e :\n;   DE = adresse de la cha\u00eene (\u00e0 ne pas modifier)\n;   B  = ligne (0 \u00e0 15)\n;   C  = colonne (0 \u00e0 63)\n; -----------------------------------------------------------------\n; NOTE: Code g\u00e9n\u00e9r\u00e9 par chatGPT, \u00e0 optimiser!\n; -----------------------------------------------------------------\nDISPLAY_ZSTRING:\n    PUSH HL\n    PUSH AF\n    PUSH DE           ; Sauvegarde DE pour pouvoir l\u2019utiliser apr\u00e8s\n\n    ; HL = ligne * 64\n    LD   A, B\n    LD   H, 0\n    LD   L, A         ; HL = B\n\n    ADD  HL, HL       ; HL = B * 2\n    ADD  HL, HL       ; *4\n    ADD  HL, HL       ; *8\n    ADD  HL, HL       ; *16\n    ADD  HL, HL       ; *32\n    ADD  HL, HL       ; *64\n\n    ; HL = HL + colonne\n    LD   A, C\n    LD   D, 0\n    LD   E, A         ; DE = colonne (temporaire)\n    ADD  HL, DE       ; HL = offset dans m\u00e9moire vid\u00e9o\n\n    ; Ajouter base m\u00e9moire vid\u00e9o\n    LD   DE, 0x3C00\n    ADD  HL, DE       ; HL = adresse \u00e9cran finale\n\n    POP  DE           ; Restaure DE = adresse de la cha\u00eene\n\n.NEXT_CHAR:\n    LD   A, (DE)      ; Lire caract\u00e8re\n    CP   0\n    JR   Z, .DONE\n\n    LD   (HL), A      ; \u00c9crire caract\u00e8re en m\u00e9moire vid\u00e9o\n    INC  DE           ; Caract\u00e8re suivant dans la cha\u00eene\n    INC  HL           ; Adresse suivante \u00e0 l'\u00e9cran\n    JR   .NEXT_CHAR\n\n.DONE:\n    POP  AF\n    POP  HL\n    RET\n\n; -----------------------------------------------------------------\n; Efface l'\u00e9cran texte (64 colonnes \u00d7 16 lignes)\n; en remplissant la m\u00e9moire vid\u00e9o avec des espaces (ASCII 32)\n; M\u00e9moire vid\u00e9o de 1024 octets \u00e0 partir de 0x3C00\n; -----------------------------------------------------------------\nCLEAR_SCREEN:\n        PUSH    DE\n        PUSH    HL\n        PUSH    AF\n        LD      DE,VSIZE\n        LD      HL, VIDEO\nLOOP_CLS:\n        LD      A,' '\n        LD      (HL),A\n        INC     HL\n        DEC     DE\n        LD      A,D\n        OR      E\n        JP      NZ,LOOP_CLS\n        POP     AF\n        POP     HL  \n        POP     DE\n    RET\n\n; -----------------------------------------------------\n\n        END     MAIN<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">Documentation de LDOS<\/p>\n\n\n\n<div data-wp-interactive=\"core\/file\" class=\"wp-block-file\"><object data-wp-bind--hidden=\"!state.hasPdfPreview\" hidden class=\"wp-block-file__embed\" data=\"https:\/\/ve2cuy.com\/blog\/wp-content\/uploads\/2025\/08\/LDOS_v5.1_for_Model_I_and_III_19xx_Tandy.pdf\" type=\"application\/pdf\" style=\"width:100%;height:600px\" aria-label=\"Contenu incorpor\u00e9 LDOS_v5.1_for_Model_I_and_III_19xx_Tandy.\"><\/object><a id=\"wp-block-file--media-093f33cd-1fb2-4dea-bc15-8126fe38570d\" href=\"https:\/\/ve2cuy.com\/blog\/wp-content\/uploads\/2025\/08\/LDOS_v5.1_for_Model_I_and_III_19xx_Tandy.pdf\">LDOS_v5.1_for_Model_I_and_III_19xx_Tandy<\/a><a href=\"https:\/\/ve2cuy.com\/blog\/wp-content\/uploads\/2025\/08\/LDOS_v5.1_for_Model_I_and_III_19xx_Tandy.pdf\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-093f33cd-1fb2-4dea-bc15-8126fe38570d\">T\u00e9l\u00e9charger<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Virtual Disk Utilities \u2013 Ira Goldklang&rsquo;s TRS-80 Revived Site (TRSTools) Les fichiers images de type IMD doivent \u00eatre convertis en format HFE avec l&rsquo;application HxCFloppyEmulator. Un autre exemple &#8211; Compter jusqu&rsquo;\u00e0 0xFFFF Afficher sans OS Documentation de LDOS<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1231","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/pages\/1231","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=1231"}],"version-history":[{"count":2,"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/pages\/1231\/revisions"}],"predecessor-version":[{"id":1233,"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/pages\/1231\/revisions\/1233"}],"wp:attachment":[{"href":"https:\/\/ve2cuy.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=1231"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}