1 2 ; Contains code licensed under CC-BY-SA by Michael Karcher 3 ; from https://retrocomputing.stackexchange.com/questions/12693/how-does-single-stepping-on-the-8086-interact-with-internal-and-external-interru/12694#12694 4 ; 2026 by E. C. Masloch 5 6 cpu 8086 7 org 256 8 start: 9 00000000 81FC[100E] cmp sp, stack.top 10 00000004 7303E96901 jb error 11 00000009 BE8100 mov si, 81h 12 0000000C E84702 call getnumber 13 0000000F 893E[0E04] mov word [counter], di 14 00000013 4E dec si 15 scan: 16 00000014 AC .: lodsb 17 00000015 3C20 cmp al, 32 18 00000017 74FB je . 19 00000019 3C09 cmp al, 9 20 0000001B 74F7 je . 21 0000001D 3C0D cmp al, 13 22 0000001F 7427 je .end 23 00000021 3C21 cmp al, '!' 24 00000023 7508 jne .notex 25 00000025 C706[F101]9090 mov word [..@multiply], 9090h 26 0000002B EBE7 jmp . 27 28 .notex: 29 0000002D 3C3F cmp al, '?' 30 0000002F 750A jne .notq 31 00000031 E82202 call getnumber 32 00000034 893E[EC01] mov word [..@counter], di 33 00000038 4E dec si 34 00000039 EBD9 jmp . 35 36 .notq: 37 0000003B 3C2B cmp al, '+' 38 0000003D 7506 jne .notplus 39 0000003F FE06[1003] inc byte [..@list] 40 00000043 EBCF jmp . 41 42 .notplus: 43 00000045 E92A01 jmp error 44 45 .end: 46 47 hook: 48 00000048 B80135 mov ax, 3501h 49 0000004B CD21 int 21h 50 0000004D 891E[A801] mov word [i01.next], bx 51 00000051 8C06[AA01] mov word [i01.next + 2], es 52 00000055 BA[A601] mov dx, i01 53 00000058 B80125 mov ax, 2501h 54 0000005B CD21 int 21h 55 56 0000005D B8A135 mov ax, 35A1h 57 00000060 CD21 int 21h 58 00000062 891E[9201] mov word [iA1.next], bx 59 00000066 8C06[9401] mov word [iA1.next + 2], es 60 0000006A BA[9001] mov dx, iA1 61 0000006D B8A125 mov ax, 25A1h 62 00000070 CD21 int 21h 63 64 %define STRINGS db "" 65 %define TABLE dw "" 66 67 %imacro i 1+.nolist 68 %assign %%entry ($ - start + 256) 69 %defstr %%string %1 70 %xdefine STRINGS STRINGS, %%name:, {db %%string, 36} 71 %xdefine TABLE TABLE, dw %%entry, dw %%length, dw %%name 72 %1 73 %assign %%length ($ - start + 256) - %%entry 74 %endmacro 75 76 00000072 90 align 64, nop 77 test: 78 ; Following from https://retrocomputing.stackexchange.com/questions/12693/how-does-single-stepping-on-the-8086-interact-with-internal-and-external-interru/12694#12694 79 00000080 9C i pushf 80 00000081 B80003 i mov ax, 300h ; 100h = TF; 200h = IF 81 00000084 50 i push ax 82 00000085 9D i popf ; This instruction sets the trace flag 83 00000086 B83412 i mov ax, 1234h 84 00000089 B301 i mov bl, 1 85 0000008B 40 i inc ax 86 0000008C 8CDA i mov dx, ds 87 0000008E 8EC0 i mov es, ax ; On 8086/8088: No interrupts before NOP is executed 88 00000090 90 i nop 89 00000091 8CD2 i mov dx, ss 90 00000093 8ED2 i mov ss, dx ; On any x86 processor: No interrupts before NOP is executed 91 00000095 90 i nop 92 00000096 CDA1 i int 0A1h 93 00000098 49 i dec cx 94 00000099 9D i popf ; This instruction clears the trace flag 95 0000009A 48 i dec ax 96 97 unhook: 98 0000009B 2EC516[A801] lds dx, [cs:i01.next] 99 000000A0 B80125 mov ax, 2501h 100 000000A3 CD21 int 21h 101 102 000000A5 2EC516[9201] lds dx, [cs:iA1.next] 103 000000AA B8A125 mov ax, 25A1h 104 000000AD CD21 int 21h 105 106 dump: 107 000000AF 0E push cs 108 000000B0 1F pop ds 109 000000B1 0E push cs 110 000000B2 07 pop es 111 000000B3 BE[1004] mov si, buffer 112 000000B6 8B3E[0C03] mov di, [next] 113 000000BA 89F8 mov ax, di 114 000000BC 29F0 sub ax, si 115 000000BE D1E8 shr ax, 1 116 000000C0 D1E8 shr ax, 1 117 000000C2 E83C01 call disp_ax_hex 118 119 000000C5 BA[1403] mov dx, msg.linebreak 120 000000C8 E8B200 call disp_msg 121 122 000000CB 8CCB mov bx, cs 123 000000CD 91 xchg cx, ax 124 000000CE CC int3 125 000000CF 803E[1003]01 cmp byte [..@list], 1 126 000000D4 7247 jb dumponly 127 list: 128 000000D6 56 push si 129 000000D7 51 push cx 130 000000D8 BE[8E02] mov si, table 131 .loop: 132 000000DB AD lodsw 133 134 000000DC BA[4D03] mov dx, msg.asterisk 135 000000DF BF[1004] mov di, buffer 136 000000E2 51 push cx 137 .next: 138 000000E3 AF scasw 139 000000E4 7406 je .found 140 000000E6 AF scasw ; di += 2 141 000000E7 E2FA loop .next 142 .notfound: 143 000000E9 BA[4F03] mov dx, msg.blank 144 .found: 145 000000EC E88E00 call disp_msg 146 000000EF 59 pop cx 147 000000F0 E80E01 call disp_ax_hex 148 000000F3 BA[5103] mov dx, msg.plus 149 000000F6 E88400 call disp_msg 150 000000F9 AD lodsw 151 000000FA E82A01 call disp_al_dec 152 000000FD BA[1103] mov dx, msg.sep 153 00000100 E87A00 call disp_msg 154 00000103 AD lodsw 155 00000104 92 xchg dx, ax 156 00000105 E87500 call disp_msg 157 00000108 BA[1403] mov dx, msg.linebreak 158 0000010B E86F00 call disp_msg 159 160 0000010E 81FE[0C03] cmp si, table.end 161 00000112 72C7 jb .loop 162 .end: 163 00000114 59 pop cx 164 00000115 5E pop si 165 00000116 803E[1003]02 cmp byte [..@list], 2 166 0000011B 7250 jb exit 167 dumponly: 168 0000011D E34E jcxz .done 169 .loop: 170 0000011F AD lodsw 171 00000120 92 xchg ax, dx 172 00000121 AD lodsw 173 00000122 E8DC00 call disp_ax_hex 174 00000125 E85C00 call disp_colon 175 00000128 92 xchg ax, dx 176 00000129 E8D500 call disp_ax_hex 177 0000012C 39DA cmp dx, bx 178 0000012E 7408 je .ourcs 179 00000130 BA[1703] mov dx, msg.not_our_cs 180 00000133 E84700 call disp_msg 181 00000136 EB33 jmp .next 182 183 .ourcs: 184 00000138 BF[8E02] mov di, table 185 .innerloop: 186 0000013B AF scasw 187 0000013C 751F jne .innernext 188 0000013E 0305 add ax, word [di + 0] 189 00000140 BA[1103] mov dx, msg.sep 190 00000143 E83700 call disp_msg 191 00000146 E8B800 call disp_ax_hex 192 00000149 BA[1103] mov dx, msg.sep 193 0000014C E82E00 call disp_msg 194 0000014F 8B5502 mov dx, word [di + 2] 195 00000152 E82800 call disp_msg 196 00000155 BA[1403] mov dx, msg.linebreak 197 00000158 E82200 call disp_msg 198 0000015B EB0E jmp .next 199 200 .innernext: 201 0000015D AF scasw ; di += 2 202 0000015E AF scasw ; di += 2 203 0000015F 81FF[0C03] cmp di, table.end 204 00000163 72D6 jb .innerloop 205 00000165 BA[2903] mov dx, msg.unknownline 206 00000168 E81200 call disp_msg 207 .next: 208 0000016B E2B2 loop .loop 209 .done: 210 211 exit: 212 0000016D B8004C mov ax, 4C00h 213 00000170 CD21 int 21h 214 215 error: 216 00000172 BA[4403] mov dx, msg.error 217 00000175 E80500 call disp_msg 218 00000178 B8014C mov ax, 4C01h 219 0000017B CD21 int 21h 220 221 disp_msg: 222 0000017D 50 push ax 223 0000017E B409 mov ah, 09h 224 00000180 CD21 int 21h 225 00000182 58 pop ax 226 00000183 C3 retn 227 228 disp_colon: 229 00000184 50 push ax 230 00000185 52 push dx 231 00000186 B23A mov dl, ':' 232 00000188 B402 mov ah, 02h 233 0000018A CD21 int 21h 234 0000018C 5A pop dx 235 0000018D 58 pop ax 236 0000018E C3 retn 237 238 retf_inst: 239 0000018F CB retf 240 241 align 2 242 iA1: 243 00000190 EB10 i jmp strict short .enter 244 00000192 00000000 .next: dd 0 245 00000196 4B42 dw "KB" 246 00000198 00 db 0 247 00000199 EBF4 jmp strict short retf_inst 248 0000019B 00 times 7 db 0 249 .enter: 250 000001A2 42 i inc dx 251 000001A3 4A i dec dx 252 000001A4 CF i iret 253 254 000001A5 90 align 2 255 i01: 256 000001A6 EB10 jmp strict short .enter 257 000001A8 00000000 .next: dd 0 258 000001AC 4B42 dw "KB" 259 000001AE 00 db 0 260 000001AF EBDE jmp strict short retf_inst 261 000001B1 00 times 7 db 0 262 .enter: 263 000001B8 55 push bp 264 000001B9 89E5 mov bp, sp 265 000001BB 06 push es 266 000001BC 57 push di 267 000001BD 50 push ax 268 000001BE 51 push cx 269 000001BF 52 push dx 270 000001C0 FC cld 271 000001C1 0E push cs 272 000001C2 07 pop es 273 000001C3 268B3E[0C03] mov di, [es:next] 274 000001C8 81FF[100C] cmp di, buffer.end 275 000001CC 7207 jb .space 276 000001CE 26FF06[0E03] inc word [es:toomany] 277 000001D3 EB0D jmp .done 278 279 .space: 280 000001D5 8B4602 mov ax, word [bp + 2] ; ip 281 000001D8 AB stosw 282 000001D9 8B4604 mov ax, word [bp + 4] ; cs 283 000001DC AB stosw 284 000001DD 26893E[0C03] mov word [es:next], di 285 .done: 286 287 000001E2 268B0E[0E04] mov cx, word [es:counter] 288 000001E7 E311 jcxz .skip 289 000001E9 FA cli 290 .outer: 291 000001EA 51 push cx 292 000001EB B9FFFF mov cx, -1 293 ..@counter: equ $ - 2 294 .inner: 295 000001EE B81541 mov ax, 16661 296 ..@multiply: 297 000001F1 F7E0 mul ax 298 000001F3 01C0 add ax, ax 299 000001F5 E2F7 loop .inner 300 000001F7 59 pop cx 301 000001F8 E2F0 loop .outer 302 .skip: 303 000001FA 5A pop dx 304 000001FB 59 pop cx 305 000001FC 58 pop ax 306 000001FD 5F pop di 307 000001FE 07 pop es 308 000001FF 5D pop bp 309 00000200 CF iret 310 311 disp_ax_hex: 312 00000201 86C4 xchg al, ah 313 00000203 E80200 call disp_al_hex 314 00000206 86C4 xchg al, ah 315 disp_al_hex: 316 00000208 51 push cx 317 00000209 B104 mov cl, 4 318 0000020B D2C0 rol al, cl 319 0000020D E80300 call disp_al_nybble_hex 320 00000210 D2C0 rol al, cl 321 00000212 59 pop cx 322 disp_al_nybble_hex: 323 00000213 50 push ax 324 00000214 52 push dx 325 00000215 240F and al, 15 326 00000217 0430 add al, '0' 327 00000219 3C39 cmp al, '9' 328 0000021B 7602 jbe .got 329 0000021D 0407 add al, 7 330 .got: 331 0000021F 92 xchg dx, ax 332 00000220 B402 mov ah, 02h 333 00000222 CD21 int 21h 334 00000224 5A pop dx 335 00000225 58 pop ax 336 00000226 C3 retn 337 338 339 disp_al_dec: 340 00000227 50 push ax 341 00000228 51 push cx 342 00000229 52 push dx 343 0000022A B90064 mov cx, 100 << 8; ch = 100, cl = 0 344 .loop: 345 0000022D B400 mov ah, 0 ; ax = dividend 346 0000022F F6F5 div ch ; ah = remainder, al = quotient 347 00000231 50 push ax 348 00000232 84C0 test al, al ; leading zero ? 349 00000234 7506 jnz .do ; no --> 350 00000236 F7C1FF01 test cx, 01FFh ; (ch & 1) == 0 (not true for 100, 10) 351 ; AND cl == 0 352 0000023A 7408 jz .dont ; then skip leading zero --> 353 .do: 354 0000023C 41 inc cx ; remember had a digit 355 0000023D 0430 add al, '0' 356 0000023F 92 xchg dx, ax 357 00000240 B402 mov ah, 02h 358 00000242 CD21 int 21h 359 .dont: 360 00000244 88E8 mov al, ch 361 00000246 D40A aam ; divide by 10 362 00000248 88E5 mov ch, ah 363 0000024A 58 pop ax 364 0000024B 88E0 mov al, ah 365 0000024D 80FD01 cmp ch, 1 366 00000250 73DB jae .loop 367 00000252 5A pop dx 368 00000253 59 pop cx 369 00000254 58 pop ax 370 00000255 C3 retn 371 372 373 ; INP: si -> text 374 ; OUT: si - 1 -> end (nondigit) 375 ; di = number 376 getnumber: 377 .skip: 378 00000256 AC lodsb 379 00000257 3C20 cmp al, 32 380 00000259 74FB je .skip 381 0000025B 3C09 cmp al, 9 382 0000025D 74F7 je .skip 383 0000025F 3C30 cmp al, '0' 384 00000261 7303E90CFF jb error 385 00000266 3C39 cmp al, '9' 386 00000268 7603E905FF ja error 387 0000026D 31FF xor di, di 388 0000026F EB01 jmp .digit 389 .loop: 390 00000271 AC lodsb 391 .digit: 392 00000272 3C5F cmp al, '_' 393 00000274 74FB je .loop 394 00000276 2C30 sub al, '0' 395 00000278 7213 jb .end 396 0000027A 3C0A cmp al, 10 397 0000027C 730F jae .end 398 0000027E 98 cbw 399 0000027F 01FF add di, di ; times 2 400 00000281 89FB mov bx, di 401 00000283 01FF add di, di ; times 4 402 00000285 01FF add di, di ; times 8 403 00000287 01DF add di, bx ; times 10 404 00000289 01C7 add di, ax 405 0000028B EBE4 jmp .loop 406 407 .end: 408 0000028D C3 retn 409 410 %imacro dumptables 1-*.nolist 411 %rep %0 412 %1 413 %rotate 1 414 %endrep 415 %endmacro 416 417 align 2, db 0 418 table: 419 0000028E 80010100[5303]8101- dumptables TABLE 419 00000296 0300[5903]84010100- 419 0000029E [6603]85010100- 419 000002A4 [6E03]86010300- 419 000002AA [7303]89010200- 419 000002B0 [8103]8B010100- 419 000002B6 [8B03]8C010200- 419 000002BC [9203]8E010200- 419 000002C2 [9D03]90010100- 419 000002C8 [A803]91010200- 419 000002CE [AC03]93010200- 419 000002D4 [B703]95010100- 419 000002DA [C203]96010200- 419 000002E0 [C603]98010100- 419 000002E6 [CF03]99010100- 419 000002EC [D603]9A010100- 419 000002F2 [DB03]90020200- 419 000002F8 [E203]A2020100- 419 000002FE [FA03]A3020100- 419 00000304 [0104]A4020100- 419 0000030A [0804] 420 .end: 421 422 0000030C [1004] next: dw buffer 423 0000030E 0000 toomany:dw 0 424 00000310 00 ..@list:db 0 425 426 msg: 427 00000311 202024 .sep: db " ",36 428 00000314 0D0A24 .linebreak: db 13,10,36 429 00000317 20204E6F7420696E20- .not_our_cs: db " Not in our CS",13,10,36 429 00000320 6F75722043530D0A24 430 00000329 2020556E6B6E6F776E- .unknownline: db " Unknown line in our CS",13,10,36 430 00000332 206C696E6520696E20- 430 0000033B 6F75722043530D0A24 431 00000344 4572726F72210D0A24 .error: db "Error!",13,10,36 432 0000034D 2A24 .asterisk: db "*",36 433 0000034F 2024 .blank: db " ",36 434 00000351 2B24 .plus: db "+",36 435 00000353 7075736866246D6F76- dumptables STRINGS 435 0000035C 2061782C2033303068- 435 00000365 247075736820617824- 435 0000036E 706F7066246D6F7620- 435 00000377 61782C203132333468- 435 00000380 246D6F7620626C2C20- 435 00000389 3124696E6320617824- 435 00000392 6D6F762064782C2064- 435 0000039B 73246D6F762065732C- 435 000003A4 206178246E6F70246D- 435 000003AD 6F762064782C207373- 435 000003B6 246D6F762073732C20- 435 000003BF 6478246E6F7024696E- 435 000003C8 742030413168246465- 435 000003D1 6320637824706F7066- 435 000003DA 24646563206178246A- 435 000003E3 6D7020737472696374- 435 000003EC 2073686F7274202E65- 435 000003F5 6E74657224696E6320- 435 000003FE 647824646563206478- 435 00000407 246972657424 436 437 absolute $ 438 439 0000040D ?? alignb 2 440 0000040E ???? counter:resw 1 441 442 alignb 4 443 buffer: 444 00000410 resd 512 445 .end: 446 447 alignb 16 448 stack: 449 00000C10 resb 512 450 .top: