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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
/*
** Called as start(argc, argv, envp)
*/
/* gs:edx points to prog_info structure. All other registers are OBSOLETE
** but included for backwards compatibility
*/
/* These symbols are for global constructors and destructors */
#if 0
.section .ctor
.globl ___go32_first_ctor
___go32_first_ctor:
.section .dtor
.globl ___go32_last_ctor
___go32_last_ctor:
.globl ___go32_first_dtor
___go32_first_dtor:
.data
.globl ___go32_last_dtor
___go32_last_dtor:
#endif
.text
.globl _start
_start:
.globl start
start:
#ifdef EMU387
pusha
push %gs
#endif
movl %eax,__hard_master
movl %esi,___pid
movl %edi,___transfer_buffer
movl %ebx,_ScreenPrimary
movl %ebp,_ScreenSecondary
cmpl $0, %edx
je Lcopy_none
movw %gs,%cx
movw %ds,%ax
cmpw %cx,%ax
je Lcopy_none
movl %gs:(%edx), %ecx
cmpl __go32_info_block, %ecx
jbe Lcopy_less
movl __go32_info_block, %ecx
Lcopy_less:
movl $__go32_info_block, %edi
addl $3, %ecx
andl $0xfffffffc, %ecx
movl %ecx, (%edi)
addl $4, %edi
addl $4, %edx
subl $4, %ecx
Lcopy_more:
movl %gs:(%edx), %eax
movl %eax, (%edi)
addl $4, %edx
addl $4, %edi
subl $4, %ecx
jnz Lcopy_more
movl __go32_info_block+4, %eax
movl %eax, _ScreenPrimary
movl __go32_info_block+8, %eax
movl %eax, _ScreenSecondary
/* Backward compatibility - do not copy this one!
** movl __go32_info_block+12, %eax
** movl %eax, ___transfer_buffer
*/
movl __go32_info_block+20, %eax
movl %eax, ___pid
movl __go32_info_block+24, %eax
movl %eax, __hard_master
jmp Lcopy_done
Lcopy_none:
movl %ebx,__go32_info_block+4
movl %ebp,__go32_info_block+8
movl %edi,__go32_info_block+12
movl $4096,__go32_info_block+16
movl %esi,__go32_info_block+20
movl %eax,__go32_info_block+24
movl $28, __go32_info_block
Lcopy_done:
#ifndef EMU387
call __setstack
#endif
xorl %esi,%esi
xorl %edi,%edi
xorl %ebp,%ebp
xorl %ebx,%ebx
movl %esp,%ebx
#ifdef MAKE_GCRT0
call mcount_init /* initialize the profiler */
#endif
movl 8(%ebx),%eax
pushl %eax
movl %eax,_environ
pushl 4(%ebx)
pushl (%ebx)
call ___main
call _main
addl $12,%esp
#ifdef EMU387
pop %gs
popa
#else
pushl %eax
call _exit
exit_again:
movl $0x4c00,%eax
int $0x21
jmp exit_again
#endif
ret
#ifdef MAKE_GCRT0
.globl __exit
__exit:
call mcount_write /* make sure we dump the output */
exit_again2:
movb 4(%esp),%al
movb $0x4c,%ah
int $0x21
jmp exit_again2
/* Here is where we initialize the timer interrupt - specific to go32 */
/* In this case, the timer calls mcount_isr */
.globl mcount_isr_init
mcount_isr_init:
movw __go32_info_block+36, %ax /* run mode */
cmp $1,%ax
jb skip_mcount
cmp $3,%ax
ja skip_mcount
movw $16,%ax
movw %ax,%gs
movzbl __hard_master,%eax /* timer is on irq 0 */
shll $3,%eax /* times 8 bpv */
/* movl $960,%eax vector 0x78 * 8 bpv */
movw %gs:(%eax),%cx
movw %cx,mc_chain
movw %gs:6(%eax),%cx
movw %cx,mc_chain_hi
movw %gs:2(%eax),%cx
movw %cx,mc_chain_sel
movl $mcount_isr,%ecx
movw %cx,%gs:(%eax)
movw $0xd8,%gs:2(%eax) /* selector 27 == 32-bit code */
movw $0x8f00,%gs:4(%eax)
rorl $16,%ecx
movw %cx,%gs:6(%eax)
movw %ds,%ax
movw %ax,%gs
skip_mcount:
movl mcount_histogram,%eax
movl $1,(%eax)
ret
/* Obtain the PC where we interrupted, and bump the histogram. We should */
/* do error checking here, but we don't. This routine is specific to go32 */
/* in some spots */
mcount_isr:
pushl %eax
cmpl $1,mcount_skip
je L0
movl 4(%esp),%eax /* get the PC */
subl $0x1020,%eax /* to fit in low..high */
andl $0xfffffffc,%eax
shrl $1,%eax /* now points to one 4-byte entry */
addl mcount_histogram,%eax
incw (%eax)
L0:
popl %eax
ljmp mc_chain /* chain to the next timer vector */
iret
#endif
.data
.globl _environ
_environ:
.long 0
.globl ___pid
___pid:
.long 42
.globl ___transfer_buffer
___transfer_buffer:
.long 0
.globl _ScreenPrimary
_ScreenPrimary:
.long 0
.globl _ScreenSecondary
_ScreenSecondary:
.long 0
.globl __hard_master
.globl __hard_slave
.globl __core_select
__hard_master:
.byte 0
__hard_slave:
.byte 0
__core_select:
.short 0
#ifdef MAKE_GCRT0
mc_chain:
.short 0
mc_chain_hi:
.short 0
mc_chain_sel:
.short 0
#endif
|