Indrekis
Indrekis

Categories

  • retrocomputing
  • cpm
  • CP/M

Tags

  • CP/M
  • retrocomputing
  • asm
  • Z80
  • i8080

Огляд

CP/M існує для кількох сімейств процесорів. Поміж восьмибітових це Z80, i8080 та i8085. Для випробувань асемблерів використовую два варіанти – чисто для i8080 і з мнемоніками Z80. Різниця між їх системами команд та мнемоніками описана, наприклад, в: “8080A/Z80 compatibility”.

Приклад, на якому буду випробовувати – тривіальний ‘‘Hello, world’’, який виводить текст за допомогою славнозвісний1 системний виклик 9 – ‘‘Output string’’, код якого передається регістром C, адреса стрічки в DE, а стрічка має закінчуватися символом ‘$’.

Коди виглядає приблизно так – подробиці дещо змінюються від асемблера до асемблера.

i8080 Hello world

; HEI80.ASM
BDOS    EQU     00005H        

        ORG     0100H         ; CP/M base of transient program area (TPA)
        MVI     C, 09H        ; Print string syscall
        LXI     D, MESSAGE    ; Pointer to string to pair D, E
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP

MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'

Z80 Hello world

; HEZ80.ASM
        .Z80
BDOS    EQU     00005H        

        ORG     0100H         ; CP/M base of transient program area (TPA)
        LD      C, 09H        ; Print string syscall
        LD      DE, MESSAGE   ; Pointer to string 
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP
        
MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'

Звичайно, різниця між асемблерами багато глибша – вона в наборах директив, швидкодії, вартості, доступності, документації і т.д. Тут я лише експериментував з використанням інструменту – а як ними щось зовсім просте скомпілювати.

Відпрацьовував в RunCPM, потім випробовував в емуляторі, і далі – на залізі.

CP/M Macro Assembler

Благословенні часи, коли асемблер йшов разом із операційною системою! Розпочнемо з MAC.COM від Digital research.

На диску 3, ‘‘Advanced utilities disk’’ є MAC.COM, який представляється CP/M MACRO ASSEM 2.0, і містить в собі копірайт: COPYRIGHT (C) 1977 DIGITAL RESEARCH 1. Про Z80 не знає, хоча той тоді вже існував. В ролі ‘‘лінкера’’ – HEXCOM.COM, копірайт: HEXCOM VERS: 3.00, містить стрічку CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH251082.

Мені трапилася бібліотека макросів Z80.LIB, яка обіцяє підтримку Z80, але, оскільки мнемоніки там трохи інші – не став розбиратися.

MAC.COM генерує HEX-файл, може також створювати файл лістингу (PRN), HEXCOM.COM робить з нього COM-файл.

Асемблюємо та запускаємо:

MAC HEI80 
HEXCOM HEI80 
HEI80 

Також, можна глянути на вміст HEI80.COM:

DUMP HEI80.COM

Зауважте, що розмір файлу міряється в блоках, і тому виводяться зайві нулі – для текстового файлу допоміг би символ 0x1A, для бінарного – ні.

Розширення за замовчуванням – .ASM, інші асемблери використовують інші замовчування. Опції описані в документації2, глава 10. ASSEMBLY PARAMETERS.

Наприклад, просимо створити лістинг (P) на диску B:, взяти асемблерний файл (A) на A:, файл з символами (S) – на B:, -L – не виводити у лістинг макроси з бібліотеки, позначені директивою MACLIB:

MAC HEI80 $AA PB SB -L

Створить HEI80.HEX:

:100100000E09110901CD0500C90D0A48656C6C6F17
:0B0110002C20576F726C64210D0A2434
:0000000000

HEI80.PRN – лістинг (першим символом був 0x0C – FORM FEED, що, певне, було зручно для друку, не наводжу його):

0005 =         BDOS    EQU     00005H        
                
 0100           		ORG     0100H         ; CP/M BASE OF TRANSIENT PROGRAM AREA (TPA)
 0100 0E09              MVI     C, 09H        ; PRINT STRING SYSCALL
 0102 110901            LXI     D, MESSAGE    ; POINTER TO STRING TO PAIR D, E
 0105 CD0500            CALL    BDOS          ; CALL BDOS
 0108 C9                RET                   ; RETURN TO CPP
                		
 0109 0D0A48656CMESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
 011B                   END

HEI80.SYM:

0005 BDOS	0109 MESSAGE

Як я переконався під час експериментів, одна дискета – дуже мало, мати можливість різні артефакти генерувати на різних дисках – корисна.

Несподівана проблема

Під час спроби скомпілювати варіант Z80, натрапив на поведінку, певне, типову тоді, але – незвичну зараз. COM-файл згенерувався, але – не працює. Глянув в SID.COM – дебаггері, немає перших команд. Дивлюся файл лістингу:

S               		.Z80
 0005 =         BDOS    EQU     00005H        
                
 0100           		ORG     0100H         ; CP/M BASE OF TRANSIENT PROGRAM AREA (TPA)
 0100 0E09      		MVI     C, 09H
S                       LD      C, 09H        ; PRINT STRING SYSCALL
L                       LD      DE, MESSAGE   ; POINTER TO STRING 
 0102 CD0500            CALL    BDOS          ; CALL BDOS
 0105 C9                RET                   ; RETURN TO CPP
 0106 0D0A48656CMESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
 0118                   END

Оці літери в першому стовпці – S, L, якраз повідомляють про помилку, з документації2, 13. ERROR MESSAGES:

  • S – “Syntax error: the fields of this statement are ill-formed and cannot be processed properly; may be due to invalid characters or delimiters which are out of place.”;
  • L – “Label error: label cannot appear in this context (may be a duplicate label).”.

Асемблер що зрозумів – згенерував, а що не зрозумів – пропустив, хоча й повідомив – рядки із лістингу із помилками надрукував на консоль.

Працює під MAME і для Osborne Executive i для Vixen і на реальному залізі. Останнє – очікувано. :-)

Фото запуску на Osborne Executive. Асемблює 9 секунд, HEXCOM працює 4 секунди.

CP/M Assembler

Повернемося на крок назад – використаємо ASM.COM, попередник MAC.COM. Візьмемо його з образу OS1UTLS.IMDCP/M 2.2 Utilities Disk диску для Osborne 1.

Перша моя спроба була саме з ним. Вийшло весело – вводжу:

ASM HELLO.ASM 

а воно мені видало:

CP/M Error On M: Invalid Drive

Диск M?! Вже потім інструкція3 підказала – розширення файлу завжди вважається ASM, після крапки йдуть опції – з якого диску взяти ASM-файл, куди зберегти HEX-файл і куди зберегти лістинг (.PRN). Літера X вказує вивести на консоль, Z – пропустити генерацію цього файлу.

Отож, треба так:

ASM HEI80 
LOAD HEI80 
HEI80 

ASM.COM з OS1UTLS.IMD представляється як CP/M ASSEMBLER - VER 2.0, має в собі стрічку COPYRIGHT(C) 1978, DIGITAL RE“EARCH – чи то з опечаткою, чи то так задумано. В LOAD.COM є така стрічка: COPYRIGHT (C) 1978, DIGITAL RESEARCH.

Працює під MAME і для Osborne Executive i для Vixen, і на реальному залізі.

Фото запуску на Osborne Executive. Асемблює 6 секунд, LOAD працює неповних 5 секунд.

CP/M Relocatable Macro Assembler

Ще один асемблер від DR, який згадується в документації – RMAC.COM, котрий компілює не в .HEX, а в .REL – об’єктний файл, запропонований, здається, Мікрософт. Знайти його виявилося важче. Один із варіантів знайдено в файлі pli80_14.zip – PL/I-80 1.4, інший, тотожний, крім 16 байтів за зміщенням 0x98 – десь на просторах Інтернету.

RMAC HEI80 
LINK HEI80 
HEI80 

Система опцій схожа на опції4 MAC.COM.

Щодо сумісності з утилітами Microsoft, з одного боку, видається, директива ASEG не потрібна (на відміну від M80) – COM файл створюється коректний. З іншого боку, використовуючи L80.COM від Microsoft я не зміг злінкувати правильно – найближчим результатом, під час експериментів, був файл, де плюс-мінус коректний бінарний код був у файлі за зміщенням 100H (0x100). Зізнаюся, глибоко не розбирався. Потужну можливість RMAC уписати програми із кількох одиниць трансляції поки не випробовував.

Цей RMAC.COM представляється як CP/M RMAC ASSEM 1.1, та містить стрічку COPYRIGHT (C) 1980 DIGITAL RESEARCH. LINK.COM виводить LINK 1.31 та містить стрічку COPYRIGHT (C) 1978, DIGITAL RESEARCH.

Працює під MAME і для Osborne Executive i для Vixen, а також – на реальному залізі.

Фото запуску на Osborne Executive. Асемблює неповних 9 секунд, лінкує 10 секунд.

Microsoft M80

З мікрософтівським асемблером було трохи веселіше. Опції суттєво відрізняються від асемблерів Digital Research, код теж потребує невеликих модифікацій.

Розширення за замовчуванням – .MAC, хоча допускає вказання іншого. Щоб успішно злінувати, потребує директиву ASEG5:

; HEI80M.MAC
BDOS    EQU     00005H        
        
        ASEG
        ORG     0100H         ; CP/M base of transient program area (TPA)
        MVI     C, 09H        ; Print string syscall
        LXI     D, MESSAGE    ; Pointer to string to pair D, E
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP
        
MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
        END 

В Інтернеті згадують також необхідність ENTRY MAIN, але в мене працювало і без того.

; HEI80M1.MAC
BDOS    EQU     00005H        
        
        ASEG
ENTRY MAIN 
MAIN:        
        ORG     0100H         ; CP/M base of transient program area (TPA)
        MVI     C, 09H        ; Print string syscall
        LXI     D, MESSAGE    ; Pointer to string to pair D, E
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP
        
MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
        END MAIN

Мінімальна команда асемблювання:

M80 =HEI80M1
L80 HEI80M1/n,HEI80M1/e
HEI80M1

Опції M80

M80 можна викликати так:

M80 obj,list=src

де obj – ім’я об’єктного файлу, list – файлу з лістингом, src – вхідного файлу, всі можуть містити літери дисків, де ці файли мають бути. Також, можна використовувати файли пристроїв. Наприклад, так – лістинг виведе на консоль, а об’єктний файл матиме те ж ім’я, що вхідний:

M80 HEI80M1,TTY:=HEI80M1
або 
M80 ,TTY:=HEI80M1/R

Де /R – примусова (цитуючи документацію – forced) генерація об’єктного файлу. /L – те ж для лістингу; /C – для файлу перехресних посилань.

Лістинг (символи FORMFEED пропущено) HEI80M1.PRN:

	MACRO-80 3.44	09-Dec-81	PAGE	1


                                ; HEI80 for MS tools 
  0005                          BDOS    EQU     00005H        
                                		
  0000'                         		ASEG
                                ENTRY MAIN 
  0000                          MAIN:		
                                		ORG     0100H         ; CP/M base of transient program area (TPA)
  0100    0E 09                         MVI     C, 09H        ; Print string syscall
  0102    11 0109                       LXI     D, MESSAGE    ; Pointer to string to pair D, E
  0105    CD 0005                       CALL    BDOS          ; Call BDOS
  0108    C9                            RET                   ; Return to CPP
                                		
  0109    0D 0A 48 65           MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
  010D    6C 6C 6F 2C           
  0111    20 57 6F 72           
  0115    6C 64 21 0D           
  0119    0A 24                 
                                        END MAIN
	MACRO-80 3.44	09-Dec-81	PAGE	S


Macros:

Symbols:
0005 	BDOS            0000I 	MAIN            0109 	MESSAGE         



No Fatal error(s)


        RET                   ; Return to CPP

Якщо не передати опції, M80 переходить в інтерактивний режим – команди можна вводити після запрошення, одну за одною.

Опції L80

L80 HEI80M1/N,HEI80M1/E

Перше ім’я вказує ім’я .REL файлу, друге – COM-файлу, створення якого замовляється опцією /N, опція /E – вийти із L80 після – інакше перейде в інтерактивний режим. Також, можна передати опцію /G – зразу виконати (але для моїх асемблерних файлів вона не запрацювала), /Y дозволяє генерувати файл символів для SID. Опції для лінкування кількох об’єктних файлів згадано в розділі про C.

Як вже казав, підтримує інтерактивний режим – мені він часто ставав у пригоді, поки навчився правильно використовувати.

Підтримка Z80

На відміну від випробуваних мною утиліт від DR, підтримується Z80:

Код:

; hez80m.mac 
        .Z80
BDOS    EQU     00005H        

        ASEG
        ORG     0100H         ; CP/M base of transient program area (TPA)
        LD      C, 09H        ; Print string syscall
        LD      DE, MESSAGE   ; Pointer to string 
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP
        
MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'

        END

Компілюється аналогічно.

Лістинг:

	MACRO-80 3.44	09-Dec-81	PAGE	1


                                        .Z80
  0005                          BDOS    EQU     00005H        
                                
  0000'                                 ASEG
                                        ORG     0100H         ; CP/M base of transient program area (TPA)
  0100    0E 09                         LD      C, 09H        ; Print string syscall
  0102    11 0109                       LD      DE, MESSAGE   ; Pointer to string 
  0105    CD 0005                       CALL    BDOS          ; Call BDOS
  0108    C9                            RET                   ; Return to CPP
                                
  0109    0D 0A 48 65           MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
  010D    6C 6C 6F 2C           
  0111    20 57 6F 72           
  0115    6C 64 21 0D           
  0119    0A 24                 
                                
                                        END
	MACRO-80 3.44	09-Dec-81	PAGE	S


Macros:

Symbols:
0005 	BDOS            0109 	MESSAGE         



No Fatal error(s)


  RET                   ; Return to CPP

Підсумок

Взаємовідносини між різними програмами пакету5, 1981 рік, Fig 1.5

Використаний M80 не виводить інформації про копірайт, цікавих стрічок я в ньому не побачив. L80 містить стрічку Link-80 3.44 09-Dec-81 Copyright (c) 1981 Microsoft, її ж і виводить при запуску. Ймовірно, версія M80 – та ж. Знайшов його на просторах Інтернету: MASM-80.ZIP.

Працює під MAME і для Osborne Executive i для Vixen, працює на реальному залізі.

Фото запуску на Osborne Executive, код 8080.
Фото запуску на Osborne Executive, код Z80.

Асемблює неповних 6 секунд і для Z80 і для 8080, лінкує 3 секунди для 8080, чомусь 8 для Z80.

SLR Systems Z80ASM

Цей асемблер багато де в Інтернеті хвалять – вирішив, що він буде наступним. Підтримує лише Z806, код, використаний вище для DR ASM/MAC/RMAC – скомпілювався зразу, єдине – приймає наперед визначене розширення .Z80, тому файл довелося назвати HEZ80.Z80.

Формат командного рядка схожий на ASM.COM – після імені файлу, відділені крапкою, можуть йти імена дисків, звідки брати текст програми, і куди зберігати згенеровані файли.

Найпростіший варіант:

Z80ASM HEZ80

Запит на генерування лістингу:

Z80ASM HEZ80/F

Результат:

Z80ASM SuperFast Relocating Macro Assembler     	    Z80ASM 1.32 Page   1
HEZ80   Z80

    1                           .Z80
    2         0005      BDOS    EQU     00005H        
    3                   
    4         0100              ORG     0100H         ; CP/M base of transient program area (TPA)
    5 0100  0E 09               LD      C, 09H        ; Print string syscall
    6 0102  11 0109             LD      DE, MESSAGE   ; Pointer to string 
    7 0105  CD 0005             CALL    BDOS          ; Call BDOS
    8 0108  C9                  RET                   ; Return to CPP
    9                   
   10 0109  0D 0A 48 65 MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
   11                   
   12                           END
 0 Error(s) Detected.
 27 Absolute Bytes. 2 Symbols Detected.

Генеруючи лістинг, асемблер зробить два проходи, без нього – може обмежитися одним.

Вміє генерувати як сумісні із мікрософтівськими .REL-файли, так і свої:

Z80ASM HEZ80/R
SLRNK HEZ80,HEZ80/N/E
HEZ80
Z80ASM HEZ80/M
L80 HEZ80,HEZ80/N/E
HEZ80

Опції лінкера схожі на L80. Детальніше – див. документацію7.

Файли SLR Z80ASM було знайдено на просторах Інтернету8 – архів із ними: SLR.ZIP. Z80ASM представляється так: Z80ASM Copyright (C) 1983-86 by SLR Systems Rel. 1.32 #AB1234, SLRNK.COM – SuperLinker Copyright (C) 1983-86 by SLR Systems Release 1.31 #AB1234, тобто, це суттєво новіші утиліти, ніж випробувані в попередніх розділах.

Під MAME/Osborne Executive відмовився працювати – отримати об’єктний файл не вдалося, взагалі вів себе нестабільно між перезапусками. Під MAME/Vixen та Osborne 1 працювало як під RunCPM. На реальному залізі теж працює.

Фото запуску на Osborne Executive. Асемблює неповних 6 секунд, лінкує 3 секунди.

Z80DIS

Пакет включає, як на той час, симпатичний дизасемблер. Виклик виглядає так:

D0>z80dis HEZ80.ddd
Z80 DISASSEMBLER Copyright (C) 1983 by SLR Systems Release 1.2
PASS 1
0008H Symbols Detected
PASS 2
FINISH

де після крапки – диски для вхідного файлу, де шукати .SYM-файл (навіть якщо його немає, треба вказати коректний диск) та – куди покласти результат.

Результат виглядає так.
	ORG	0100H


L0100
	LD	C,09H		;HT
	LD	DE,L0109
	CALL	0005H		;PRNTSTG
	RET	
L0109
	DEC	C
	LD	A,(BC)
	LD	C,B
	LD	H,L
	LD	L,H
	LD	L,H
	LD	L,A
	INC	L
	JR	NZ,L016A
	LD	L,A
	LD	(HL),D
	LD	L,H
	LD	H,H
	LD	HL,0A0DH
	INC	H
	LD	A,(BC)
	INC	H
	ADD	HL,DE
	LD	C,L
	ADD	A,(HL)
	JP	0B078H
	LD	B,B
	LD	D,A
	SCF
	SBC	A,H
	ADC	A,L
	ADD	A,(HL)
	LD	B,C
	EX	AF,AF'
	INC	(HL)
	INC	D
	INC	H
	SBC	A,H
	NOP
	NOP
	NOP
	SBC	A,(HL)
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
L016A
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	END

Видно, що стрічку згорнути не зміг, і що CP/M не зберігає розміри файлів… Файл .SYM мав би допомогти вирішити ці проблеми, але з першої спроби не вдалося, MAKESYM чи SLRNK створюють порожній файл символів. Потім, натрапивши на приклад – DUMP.SYM, вдалося написати HEZ80.SYM – в реальному житті, він би створювався покладаючись на попередній вивід та розпізнавши там стрічку:

%st	0100
%en	011c
%ls
%ax

%db	 0109-011b

msg	 0012

Якщо його ‘‘згодувати’’ z80dis.com, поведінка дизасемблера змінюється, і замість асемблерного файлу, він створює HEZ80.LST:

0000		  00001 	ORG	0100H
0100		  00002 
0100		  00003 MSG	EQU	0012H
0100		  00004 
0100		  00005 L0100
0100  0E 09 	  00006 	LD	C,09H		;HT
0102  11 09 01 	  00007 	LD	DE,L0109
0105  CD 05 00 	  00008 	CALL	0005H		;PRNTSTG
0108  C9 	  00009 	RET	
0109		  00010 L0109
0109  0D 0A 48 65 00011 	DEFB	0DH,0AH,48H,65H,6CH,6CH		; ..Hell
010F  6F 2C 20 57 00012 	DEFB	6FH,2CH,20H,57H,6FH,72H		; o, Wor
0115  6C 64 21 0D 00013 	DEFB	6CH,64H,21H,0DH,0AH,24H		; ld!..$
011B  00 	  00014 	DEFB	00H				; .
011C		  00015 	END

Не IDA, і навіть не Sourcer9, але враховуючи епоху – круто.

2500 A.D. SOFTWARE ASM

Виглядає, теж був популярним асемблером. Цікаво, що існував не тільки для UNIX та MS-DOS, але й для VMS. На жаль, інформації про нього мало – поки документацію вдалося знайти лише для версії 4.0210, а сам асемблер для Z80 – лише 2.07d, і між ними велика різниця, від іншого імені виконавчих файлів, через інші назви інтерактивних команд, до відсутності в 2.07d директиви .CODE.

Представляється цей ASM.COM так: Z80 MACRO ASSEMBLER VERS. 2.07d - COPYRIGHT (C) 1982 BY 2500 A.D. SOFTWARE, INC. Його LINK.COM: 2500 A.D. Z80 MACRO ASSEMBLER LINKER - VERSION 2.07c.

Через це, на жаль, поки не вдалося розібратися із тим, як його використати з командного рядка – успішно побудувати програму вдалося лише з інтерактивного режиму. Аналогічно, не вдалося добитися виведення лістингу у файл.

Код довелося модифікувати. Зокрема, незвичним було, що пробіли між операндами команд заборонені.

; HEZ80AD.ASM 
BDOS    .EQU     00005H        

        .ORG     0100H       ; CP/M base of transient program area (TPA)
        LD      C,09H        ; Print string syscall
        LD      DE,MESSAGE   ; Pointer to string 
        CALL    BDOS         ; Call BDOS
        RET                  ; Return to CPP
		
MESSAGE:.DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'

        .END
Сеанс компіляції під RunCPM. ``` E0>asm Z80 MACRO ASSEMBLER VERS. 2.07d - COPYRIGHT (C) 1982 BY 2500 A.D. SOFTWARE, INC SERIAL # 001-004-0095 This Program is proprietary information of 2500 A.D. SOFTWARE, INC. It is not to be copied or duplicated in any form without written consent. LISTING DESTINATION ? (TI,LP,NL,DL) TI INPUT FILENAME ? : hez80ad.asm OUTPUT FILENAME ? : hez80ad.obj *** ACTIVE COMMANDS *** ^S = START/STOP OUTPUT ^C = TERMINATE ASSEMBLY ^T = TERMINAL OUTPUT ^P = PRINTER OUTPUT ^N = NO OUTPUT 2500 A.D. Z80 MACRO ASSEMBLER - VERSION 2.07d ------------------------------------------------- INPUT FILENAME : HEZ80AD.ASM OUTPUT FILENAME : HEZ80AD.OBJ 05 00 BDOS .EQU 00005H 0100 .ORG 0100H ; CP/M base of transie nt program area (TPA) 0100 0E 09 LD C,09H ; Print string syscall 0102 11 09 01 LD DE,MESSAGE ; Pointer to string 0105 CD 05 00 CALL BDOS ; Call BDOS 0108 C9 RET ; Return to CPP 0109 0109 0D 0A 48 65 MESSAGE:.DB 0DH,0AH,'Hello, World!',0DH,0AH,'$' 010D 6C 6C 6F 2C 0111 20 57 6F 72 0115 6C 64 21 0D 0119 0A 24 011B .END 0000 ASSEMBLY ERRORS E0>link 2500 A.D. Z80 MACRO ASSEMBLER LINKER - VERSION 2.07c - Carriage return after FILENAME prompt ends input filenames. - Carriage return after ADDRESS prompt stacks object code. - Dash (-) before LOAD ADDRESS uses file for Global values only. - Carriage return after OUTPUT prompt uses 1st input filename. - Input default extension is .OBJ , output is always .COM - Control P will send the output to the printer. INPUT FILENAME ? : HEZ80AD.OBJ LOAD ADDRESS (OFFSET) ? : 0 INPUT FILENAME ? : OUTPUT FILENAME ? : HEZ80AD.COM 2500 A.D. Z80 MACRO ASSEMBLER LINKER - VERSION 2.07c PAGE 2 ************************************************** * L O A D M A P * ************************************************** * FILENAME STARTING ENDING SIZE * * ADDRESS ADDRESS (BYTES) * ************************************************** * HEZ80AD.OBJ 0100 011A 001B * ************************************************** 0000 LINK ERRORS GENERATING LOAD FILE E0>HEZ80AD Hello, World! ``` TI -- підказує новіша документація, що вивід на термінал. На жаль, з DL -- потенційно, вивід на диск, не вдалося дати раду. Вертикальне місце вивід зовсім не економить...

На RunCPM працює, в MAME-емуляції Osborne Executive, не працює, але на емуляторі Vixen – працює як в RunCPM, на реальному залізі – працює.

MAME/Osborne Executive – каже ILEGAL MNEMONIC і, якщо тиснути Return - - пищить і виводить “крякозябри” та іноді зависає. Іноді навіть ще при запуску асемблера.
Фото запуску на Osborne Executive – 1.
Фото запуску на Osborne Executive – 2.
Фото запуску на Osborne Executive – 3.
Фото запуску на Osborne Executive – 4.

Асемблює повільно – під 20 секунд, лінкує – 28 секунд (не рахуючи часу на введення аргументів). Із запасом, повільніше, ніж інші тут розглянуті.

MITEK Relocating Macro Assembler

Ще один асемблер з просторів Інтернету. Локальна копія тут, документація є для приблизно тієї ж епохи11.

Представляється MITEK Relocating Macro Assembler vers 2.5, ZLINK – MITEK Linking loader vers 2.3, ZCOV – MITEK 8080 to Z80 source converter vers 2.1.

Як і інші Relocating, потребує ASEG (принаймні, як один із варіантів). Виклик із генерацією лістингу:

zas hez80.asm $PF 
zlink hez80
hez80

Отриманий лістинг:

MITEK Relocating Macro Assembler vers 2.5                             page    1
                                                            
                                                            

  0000           ;               .Z80
  0005 =         BDOS    EQU     00005H        
  0000                   ASEG
  0100                   ORG     0100H         ; CP/M base of transient program area (TPA)
  0100 0E09              LD      C, 09H        ; Print string syscall
  0102 110901            LD      DE, MESSAGE   ; Pointer to string 
  0105 CD0500            CALL    BDOS          ; Call BDOS
  0108 C9                RET                   ; Return to CPP
  0109                           
  0109 0D0A48656CMESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
  011B           
  011B                   END

**** Symbol table ****
BDOS            0005 MESSAGE         0109 
E, MESSAGE   ; Pointer to string 
  0105 CD0500            CALL    BDOS          ; Call BDOS
  0108

i8080 безпосередньо не підтримує, але містить конвертер в Z80:

zcon hei80.asm

Який створює такий файл – вже нам знайомий, насправді:

BDOS    EQU     00005H        

        ASEG
        ORG     0100H         ; CP/M base of transient program area (TPA)
        LD     C, 09H        ; Print string syscall
        LD     DE, MESSAGE    ; Pointer to string to pair D, E
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP
		
MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'
        END

З MS L80 сходу не запрацювало.

Працює на RunCPM, але зависає під MAME на Executive, Vixen, і на реальному залізі.

Фото запуску на Osborne. Зависає намертво.

ZSM / Z80ASMUK

Цей асемблер – якщо й не сучасний, то ще підтримуваний та ще й Open Source: github репозиторій має, на момент написання, комміти 2020 року. Його підтримує (підтримував?) MiguelVis, в тому числі, додаючи свої утиліти. Знає лише про Z80 (хоча, код вказує, що можна скомпілювати так, щоб сам працював на i8080), тому не потребує (і не знає про неї) директиву .Z80:

BDOS    EQU     00005H        

		ORG     0100H         ; CP/M base of transient program area (TPA)
        LD      C, 09H        ; Print string syscall
        LD      DE, MESSAGE   ; Pointer to string 
        CALL    BDOS          ; Call BDOS
        RET                   ; Return to CPP
		
MESSAGE:DB      0DH,0AH,'Hello, World!',0DH,0AH,'$'

        END

Опції передаються після крапки – диск звідки брати код, куди зберігати .HEX-файл і .PRN-лістинг. @ – означає диск за замовчуванням, Z – не виводити, X – на консоль, P – в LST:, Y – на консоль, а помилки в .LST-файл. Вимагає для вхідного файлу розширення .ZSM. Що приємно, про все це видає підказку.

Виклик:

zsm hez80.@@@
hextocom hez80
hez80

Працює під MAME Osborne Executive та Vixen, також – на реальному залізі.

Фото запуску на Osborne. Асемблює 5 секунд, hextocom працює менше 5 секунд.

Підсумок

Тестування асемблерів показало, справді, емуляція Executive в MAME недосконала – лише асемблер від MITEK завис і на реальному залізі, а ті що дивним чином глючили в емуляторі, на комп’ютері відпорацювали успішно.

Час виконання, доволі відтворюваний, оцінює мінімальний час, потрібний, щоб скористатися кожним з інструментів – через простоту самої асембльованої програми. ПЗ від 2500 AD гальмувало найбільше, воно ж – найбільш багатослівне, асемблери від DR були в міру повільні – ASM найшвидший із них, майже на рівні конкурентів, але і дуже простенький, утиліти від Мікрософт та сучасний ZSM – шустрі.

Повторюся, різниця в потужності використаних асемблерів величезна, вона не може проявитися на такій простій програмі.

Як передавати опції – різнобій. Але проглядається дві тенденції – або CP/M-way (ймовірно, запозичений від якихось більших систем) – розширення визначене наперед, а після крапки – диски розташування різних файлів, варіант – PIP-подібний інтерфейс з “=”, в продукті MS, або схожий на звичний нам – через “/”, але, все ж, відмінний в подробицях. Незвичним видався і інтерактивний режим.

Кілька годин експериментів створили в мене відчуття, що такі інтерфейси доволі зручні на тих машинах, враховуючи клавіатуру і можливості відповідних комп’ютерів. В цілому, якщо знати, як користуватися, враження від використання були приємні, іноді кращими за відчуття від інструментів епохи DOS – можливо, через більші очікування. З іншого – наочно видно, наскільки потужніші, хай і з своїми проблемами, типу повільного часу реакції, є сучасні інструменти.

На цьому з асемблерами все. Хіба що – див. також пост про дебагери.

Додаток – образи дисків, використані в цьому пості

Для зручності створив образи із пакетами асемблерів, які тут випробовував. Вони не завжди містять все із архівів, звідки брав – щоб вмістилося на диск. Також, на них є відповідні асемблерні файли – щоб можна було зразу спробувати.

В асм-файли якось прокралися табуляції в кількох рядках – це видно на скрінах вище, не став через це переробляти образи та скріни.

Додаток – порівняння мнемонік Z80 та i8080

Взято із “8080A/Z80 compatibility

  • Регістри та прапорці i8080 є і в Z80.
  • Всі команди i8080 реалізуються Z80.
  • Z80 має багато додаткових регістрів та команд.
  • Однак, мнемоніки – різні. Ймовірно, щоб уникнути судових позовів.
  • Між деякими спільними командами є невелика різниця в поведінці.
  • Таймінги інструкцій, звичайно, різні.
  • Див. також вікіпедію.
Різниця в поведінці команд. Детальніше про їх причини, наприклад, обговорення тут: “Why did the Z80 break 8080 compatibility?
Порівняння регістрів та прапорців.
Порівняння мнемонік. Ремарка: у “8080A/Z80 compatibility”, звідки взято цю та інші ілюстрації розділу, є і зворотня таблиця, де багато полів для i8080 – порожні, оскільки відповідні команди відсутні.

Виноски

  1. '’Ask Bill [Gates] why the string in [MS-DOS] function 9 is terminated by a dollar sign. Ask him, because he can’t answer. Only I know that.’’, цитуючи за “Bill Gates: Of Mind and Money”, “Seattle Post-Intelligencer” Newspaper, May 8, 1991. Цей системний виклик з 1970-х, відтворений DOS 1.00 в 1981, все ще вивчали в деяких провідних ВИШах не пізніше 2020-го… 

  2. '’CP/M MAC MACRO ASSEMBLER: LANGUAGE MANUAL AND APPLICATIONS GUIDE’’, 1980; Вона ж, 1977 року 2

  3. CP/M ASSEMBLER (ASM) USER’S GUIDE, 1978

  4. 2. RMAC RELOCATING MACRO ASSEMBLER із '’LINK-80 OPERATOR’S GUIDE’’, 1980

  5. Microsoft Utility Software Manual, 1978, Microsoft Utility Software Manual for 8080 microprocessors, 1981, CREF-80, LIB-80, LINK-80, MACRO-80 2

  6. Надає бібліотеку 8080.MAC для підтримки мнемонік i8080 – поки не випробовував. 

  7. '’Z80ASM: Z80 Relocating Macro Assembler USER’S GUIDE’’, 1984, '’SLRNK: Super-Linker USER’S GUIDE’’, 1984 

  8. Ймовірно, десь тут або тут

  9. Документація Sourcer). 

  10. 2500 A.D. Z80 Macro Assembler, v. 4.02, версія для i8085 не допомогла. 

  11. '’RELOCATING MACRO ASSEMBLER AND LINKER FOR Z80 AND HD64180’’, 1985