-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathHistory.txt
110 lines (86 loc) · 3.59 KB
/
History.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
These macros are loosely based on PDP10 Macro macros that appeared at my
highschool back in the 1970s, published in some DEC10-related news media. I
don't even remember the details.
Similar but more complex macros occur in DEC's MACSYM.MAC file,
and struct.mac on DECUS decus/20-0143 by Robert Nix.
The original (macro-10) definitions that followed me from HS are attached
at the bottom of this file.
I found them useful, and later duplicated their logic in Microsofts x86
assembler (MASM.) Then I switched to doing most of my programming in C, and
the nicities of good assembler macros were mostly forgotten.
There are other implementations of similar schemes, usually implemented as a
co-processor or special assembler version (eg HLASM)
More recently, an article on using FORTH-like logic to implement structured
control flow "In any assembler" appeared.
(http://dkeenan.com/AddingStructuredControlFlowToAnyAssembler.htm ) This was
shortly clarified to be "any assembler EXCEPT the GCC Assembler", because
the Gnu assembler does not allow one of the primitive operations that they
utilized.
This is particularly frustrating because the gnu assembler supports SO many
different cpu architectures. While the Gnu assembler may have started out
as a not-quite-compatible assembler for inline use by the C compiler, it is
now the only assembler available for some CPUs. A "structured assembler"
implementation for gas would be potentially useful for a lot of people.
So I went on a search for a way to implement macros within gas that would
provode similar capabilities. It was a lot easier, and cleaner, once I
discovered ".altmacro" and decided to try to use gas's "local label"
capability.
; Here are the original Macro-10 macros.
DEFINE %LOOP <SAVCTR==SAVCTR+1
%STNAM(SAV,\SAVCTR,.)>
DEFINE LOOPER(INSTRC)
<IRP INSTRC, <DEFINE %'INSTRC(AC) <INSTRC AC,<%GTNAM(SAV,\SAVCTR)>
SAVCTR==SAVCTR-1>>>
LOOPER (<AOBJN,JRST,JUMPN,SOJG,SOJGE,SOJA,JUMPGE,AOJA>)
DEFINE %IF
<BEGCTR==BEGCTR+1
JRST <%GTNAM(BEG,\BEGCTR)>
SAVCTR==SAVCTR+1
%STNAM(SAV,\SAVCTR,BEGCTR)>
DEFINE %ELSE
<%VAL==%GTNAM(SAV,\SAVCTR)
BEGCTR==BEGCTR+1
JRST <%GTNAM(BEG,\BEGCTR)>
%STNAM(BEG,\%VAL,.)
%STNAM(SAV,\SAVCTR,BEGCTR)>
DEFINE %END
<%VAL==%GTNAM(SAV,\SAVCTR)
SAVCTR==SAVCTR-1
%STNAM(BEG,\%VAL,.)>
DEFINE %GTNAM(VAR,IND) <VAR'IND>
DEFINE %STNAM(VAR,IND,VAL) <VAR'IND=VAL>
;;; We try to make use of the gnu assembler's "local labels.
;;; So an "if" statement ends up like:
;;; brnCC 0f
;;; if code
;;; rjmp 1f ; else
;;; 0:
;;; else code
;;; 0:
;;; 1: ; endif
;;;
;;; When there is no else clause, this simplifies to:
;;; brnCC 0f
;;; if code
;;; 0: ; endif
;;; 1:
;;;
;;; Because the local lables can be redefined, and the Nf form use as a jump
;;; target jumps to the nearest label N, the start of the else and the endif
;;; can both define the same target label.
;;; But we still need some symbol munging magic to handle nesting.
;;; a counter __ST_IFNEST is maintained, indicating the current nesting.
;;; An "else" defines label __ST_IFNEST,
;;; and an "endif" __ST_IFNEST and __ST_IFNEST+1
;;; Another "if" adds two to __ST_IFNEST
;;;
;;; _st_mkjmp generate a jump to one of our defined local labels.
;;; _st_label
;;; define a local label here (at "."), depending on the counter "ind",
;;; and optional prefix
;;; elseif is annoying, because we want to jump around the clause
;;; (from the successful if clause immediately preceeding) before
;;; doing the test for the new condition.
;;; Looping macros. "until cc" will generate a jmp_not_cc backward,
;;; and "while cc" will generate a jmp_cc backward.
;;; Nesting level initialization