From 79328f9ad6f3118fd86c1f99f672d2807917d848 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 4 Dec 2018 12:26:27 -0800 Subject: [PATCH] 4841 New helper: print an error message, then a numeric byte, then abort. --- html/subx/065error-byte.subx.html | 161 ++++++++++++++++++++++++++++++ subx/065error-byte.subx | 94 +++++++++++++++++ subx/apps/crenshaw2-1 | Bin 7509 -> 7678 bytes subx/apps/crenshaw2-1b | Bin 8070 -> 8239 bytes subx/apps/factorial | Bin 6400 -> 6569 bytes 5 files changed, 255 insertions(+) create mode 100644 html/subx/065error-byte.subx.html create mode 100644 subx/065error-byte.subx diff --git a/html/subx/065error-byte.subx.html b/html/subx/065error-byte.subx.html new file mode 100644 index 00000000..22660d7d --- /dev/null +++ b/html/subx/065error-byte.subx.html @@ -0,0 +1,161 @@ + + + + +Mu - subx/065error-byte.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/065error-byte.subx +
+ 1 # Print an error message followed by the text representation of a byte. Then exit.
+ 2 
+ 3 == code
+ 4 #   instruction                     effective address                                                   register    displacement    immediate
+ 5 # . op          subop               mod             rm32          base        index         scale       r32
+ 6 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+ 7 
+ 8 # main:
+ 9     # manual test
+10 #?     # . var ed/EAX : exit-descriptor
+11 #?     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+12 #?     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   .               .                 # copy ESP to EAX
+13 #?     # . configure ed to really exit()
+14 #?     # . . ed->target = 0
+15 #?     c7/copy                         0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
+16 #?     # . error-byte(ed, Stdout, msg, 34)
+17 #?     68/push  0x34/imm32
+18 #?     68/push  "abc"/imm32
+19 #?     68/push  Stdout/imm32
+20 #?     50/push-EAX
+21 #?     e8/call  error-byte/disp32
+22     # automatic test
+23     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
+24     # . syscall(exit, Num-test-failures)
+25     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+26     b8/copy-to-EAX  1/imm32
+27     cd/syscall  0x80/imm8
+28 
+29 # write(out, "Error: "+msg+": "+byte) then stop(ed, 1)
+30 error-byte:  # ed : (address exit-descriptor), out : (address buffered-file), msg : (address array byte), n : byte -> <void>
+31     # . prolog
+32     55/push-EBP
+33     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+34     # write-buffered(out, "Error: ")
+35     # . . push args
+36     68/push  "Error: "/imm32
+37     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+38     # . . call
+39     e8/call  write-buffered/disp32
+40     # . . discard args
+41     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+42     # write-buffered(out, msg)
+43     # . . push args
+44     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
+45     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+46     # . . call
+47     e8/call  write-buffered/disp32
+48     # . . discard args
+49     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+50     # write-buffered(out, ": ")
+51     # . . push args
+52     68/push  ": "/imm32
+53     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+54     # . . call
+55     e8/call  write-buffered/disp32
+56     # . . discard args
+57     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+58     # print-byte(out, byte)
+59     # . . push args
+60     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x14/disp8      .                 # push *(EBP+20)
+61     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+62     # . . call
+63     e8/call  print-byte/disp32
+64     # . . discard args
+65     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+66     # write-buffered(out, Newline)
+67     # . . push args
+68     68/push  Newline/imm32
+69     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+70     # . . call
+71     e8/call  write-buffered/disp32
+72     # . . discard args
+73     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+74     # . flush(out)
+75     # . . push args
+76     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+77     # . . call
+78     e8/call  flush/disp32
+79     # . . discard args
+80     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+81     # stop(ed, 1)
+82     # . . push args
+83     68/push  1/imm32
+84     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+85     # . . call
+86     e8/call  stop/disp32
+87     # should never get past this point
+88 $error-byte:dead-end:
+89     # . epilog
+90     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+91     5d/pop-to-EBP
+92     c3/return
+93 
+94 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/subx/065error-byte.subx b/subx/065error-byte.subx new file mode 100644 index 00000000..82cfd21e --- /dev/null +++ b/subx/065error-byte.subx @@ -0,0 +1,94 @@ +# Print an error message followed by the text representation of a byte. Then exit. + +== code +# instruction effective address register displacement immediate +# . op subop mod rm32 base index scale r32 +# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes + +# main: + # manual test +#? # . var ed/EAX : exit-descriptor +#? 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +#? 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX +#? # . configure ed to really exit() +#? # . . ed->target = 0 +#? c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX +#? # . error-byte(ed, Stdout, msg, 34) +#? 68/push 0x34/imm32 +#? 68/push "abc"/imm32 +#? 68/push Stdout/imm32 +#? 50/push-EAX +#? e8/call error-byte/disp32 + # automatic test + e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. + # . syscall(exit, Num-test-failures) + 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + b8/copy-to-EAX 1/imm32 + cd/syscall 0x80/imm8 + +# write(out, "Error: "+msg+": "+byte) then stop(ed, 1) +error-byte: # ed : (address exit-descriptor), out : (address buffered-file), msg : (address array byte), n : byte -> + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # write-buffered(out, "Error: ") + # . . push args + 68/push "Error: "/imm32 + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # write-buffered(out, msg) + # . . push args + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16) + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # write-buffered(out, ": ") + # . . push args + 68/push ": "/imm32 + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # print-byte(out, byte) + # . . push args + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20) + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call print-byte/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # write-buffered(out, Newline) + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . flush(out) + # . . push args + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # stop(ed, 1) + # . . push args + 68/push 1/imm32 + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) + # . . call + e8/call stop/disp32 + # should never get past this point +$error-byte:dead-end: + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +# . . vim:nowrap:textwidth=0 diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index fbe0c10a2e5101c64cd97a59cd6836e07023fd24..45f0e34c17e21ae359266e477ac34537e8390df0 100755 GIT binary patch literal 7678 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 literal 7509 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 diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index fecd6c39bb9b1f39e45ccf95c428992de464f3a4..f3afe6f24ddff88fe39dfee54b025df79e2bc807 100755 GIT binary patch literal 8239 zcmbVReQ;FO6@LqxWQhw2iUJ~W#n4L4l3>&(v36J!7DiIth$VbU+$1l&Z8p2>?%M&T ziI}!p!kg_(NA0w=woW@8KdNG}wsCYS8Wn1xQ>Lw7RQrcTUmL8SRcg`g`JMaTy)Vl$ zL&?nE-Fxoup6_$+eJ?v!bVhwXpXUBe)23^fnVL4^QkO{ImuewxnlpFS83Wvnb2Sa0 z3ar;^y#LQMr%yFL8v~k#Po=Xyc4TyTF{5t2$k;nit1g<019s;eO&fidVA_=ske_LP z=NwJ57CuRU$;Q#6SSk4H_koEPGoXwCpm7xe>@(@t=(8kTdxAdNI93kc^3|~;u`cHR zsvqk#Xro8ZqOlOH-xmo~(XTH1o*H+JpmXR`EB4$0H1jm}3oV28BE~`&V1o8X^iybU z{Kmz6HcQg}>eBwHXcG6Lq8)c}&nTM2JuGSK*Nq*$VS=nGUIxe7i=WkR*lsiXnkR1o)PlG_mevWys)VzXjMSO&gqf0 z_T9_}&U55GAPFqD=GNWCVsWgdXYX48vxdrWC$$I6E&Xydf9jw<*s_|02oOaf+ zI9SN|tw13-i`rVi>JC~x{?O}!15#$vVKPdznhCp)tSq(6Xr(P&foXWmRA9;7P+qdMsC1~C3x6ZLPk*_TJ(tw-cuZw_yfRO3!)$TvQXiEJQOXIka( zT>v46V|Ja=Uu;_-d3hz^zUahrTuS&c-#(RunMwjn{FEI>J2m6C*hG;ei4Sr|^~CUg zd5QH(yj@a7Nj{>Oy#{6^s~EF;6f^rR`d#Y&GL;b}Eu6||^Av`t04qv`fr3~`g@Hm5 z^u6pZJ@)R^SpelB& zc~N?G6%*O30Ewt9W7jgV;yfY}hFlpZg6KTP5>O+(l$qFs1Fl0ZI-NbDq_Om6Y97IE z&YBlwIU99N+i ze8ziF7fY0{N*$rh9oL!D@bPV=rS0+Y5}3`zRmwq)AVzwtwQ;PVS} zWKp45d_@x9RX)BB#P;frYRUI0cA$tIYY|ehOG*|GDHa(J$!kirVa0+RgJP|vCyma4 zzl(2s?uCcWUa|lk+PxC;s}_FX;+y656eYTKQL@jWN0XVYFOAIDRk!o}<sk4Qk3+-u<*kQC&aj$VoAbfQ^7hI1xHZs)8jG^=7huqL zX|VSw@7)O^#hzNl-Ll9gjHf}~5A1CUdjLeRjM+DNu*X53UPsss3R_KchwlmxwgKd3 zV3#Uv8;FAMd=HlM{%oR)Hnfl4IMU5?LOqMFfh(T)AtlaOyPv<816hu!@9R=IPeY)P4Cih$$Kx(Cop-|JdmL@E>&}~giq)dH_o`vKsx*1O8 zhuT7BIvpB{r?!Xs6I&8yE|f@xh~BH?rKi?>Aq~+`I0SXV&Yo~qkN4-oxkPG9QV;Vs z#x|70#(UFQGZ#*$!YTSNIGjj@JJabwnAuG4OFvg`pO7(>PnwC0D zJdjQ%(_8iaaPM~Lz$(BQE3(;iwk<>tI$B8ImeKo6z28GeO}2#)D2fg0O}b%gHeu@F z-u%FTo+Y-z571_M3WkNbgU?iO)bXpEKG*{H6DY`r~GN`ROpo zr(71j+bLT3e~?rnlO>U4zp0<=B|C-?*<*y`7MLIDMYc&U0-iG|G(*k?#JwFu$HJ2$ zdy&=^Sv;{n6+}a3CM!-5H}U3ghFv35#jVecp#C~1)ICCjsBeNY-=x3|T$C5 Q8G7F!`fpA|5gESpe{LRS5&!@I literal 8070 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 C!aoTB diff --git a/subx/apps/factorial b/subx/apps/factorial index 83dab08542fe9fde077cf5c9affff1f2551443c6..befd01b606295e0726535c67e4b891dcdfc6b212 100755 GIT binary patch delta 2692 zcmZuzZD?FY6n%Ml+fBAF+1+gNk`UXbt?{GMx@{5DXplAAQd>5DOyphc@k4O6V^^sIK?k*`50cDcz4b zbLN~g_s+cRz>cw&|7kw8H26UsvHBlz zKZ_WF?D4uH*%CC2!MP%!G@?Lni5v|Z#*l9$^2x=vTXL$o`H}UOl&TABN+z?IaHjdr%f39aA89BYSf(v)Ws?JW;UD6 zxzl)w(vZ^vl42dN8EF*FcH6R!>PF>o$!L?7%o!!g$=0yDtes4D`UgR5ky4Jz#ZnB6 z!fr!3%;6?UG23m)Nj;g7^^jm?6B0x5I{TWm5;A6pA+x89qSZioRLMX{1PiP8(Ej#w z3L5uOM?}B1#e^o0TVJRq{{nX)mwXvczMSXrcc@9=s|4an zr?KkVR!%cV?j4>zcdylZR_wP}mn2(!(Bz!)O>OiyY$kV(kfoN+|ECYvUz)kF8uKhO zmyy{N_eA|S$F72+fb!kaoWxzm1Bqi(PwAIKn(%0YeU;yzR$3Hy+c z>)B83qeg3aJMFWM>O$<$7Uv6fA;_YHEol5N?G)3x^|%OX50+okjq%*9F_J+V9^XNK z`Qx;Dl2;$X)gYct$W~r0Z^L)0&$zWg{OLcTYBb9akSJU}Il<$1b@aUiQgx7|_P(9+ z6PQFMa3F6x0J#f$0nu0o1jR-8n277ij2lm)U5xF>emjq6wEd3-x^iqk#Ruc6W`4OE zGsVn#WYQ6eMv^Mi6}pz50#A?z^?@Rd^7s#JRKJ?hMmFM{HiHtELzSRRPx}pVy*P;X z_I7cPS>}ktfvCC55yOEe)n(owmI8gMM>Bj<+8mIehs+CH{v!xdp>YNa{XShy&!+lV zBB>?9EOAPM_c?FMc`#qDyzpigmS4elJWwNcjrmeUth1Z&Y1Co2CSSqUdQx9NbprRY z<(NtxFw!`KsVnI=sno>wr2bw@_*mix4c_C_3(f&d9f$|C@GRXKk8mxQP7%q7aTT)#5T$jHR@U`$JuW*VWf^Z(7t>@_YDx;?meipeOF?SDwD4dY*c(^AJ zK8f6B=ANn)*Gem#OE`BK=eF_Ow76T^xUm}wmuj+R@H5>Es*3}M=`VjfXwzNa7wmR! zp}-kz$q) zb{nH%?StTr5kve9FPLf-V%(&fqT9X@oA@Baq>&h7lX++qV&Gx5tmm9NbI(+}>CEgs z=eyte&d;6gnGL18kN57pkkT}~3=KZbn$`f1hb+2Gc$(jbH4QKLBY$~e?3FyBj^5_n z06_i4eAJz7(zLOeC_uW9U^L-IfOFiaStm~K>Vn8eiuWG&BWn*)jbB^$8V}x zVyaxzE+>bs15v7a*?O>a0ajVQ80DLDKq2 z+|4IdREGlHqA0yU;W;&R&2{Guk98HMaBU#;&jkjw%|?{*@no%P(aj3Oo@`{{me_0+l`_M{D2B{9dh)B z0#S17>2*S(L)g5KTzCeR&eXGyBu}1+#tLBD$k({!|=^z9gkj>q_KFoQg?a|ENT7A|sUn zK~lnco{CF|1Pmx0q(ehTu7*~c72Je}yH`1@&O{Nz6*wG)U(ajH_9I<@3HN4&!=K{` z$SUMVDLDV~q7RrD=f`ft&=>_8r&^A||y5K~-I z6e*^dSH^!>>#w%ymukWiN8`DU8uZJ1*Esmw;3m|tm5uY3_$uCmubx_bM{x#Q8&F=u z2xQ#EVYLh?H?<0Sa6GbfV5D+F2b8xWnv4chtX9S=tbA=|Gb%TGO+`FSN(00|KnF!P?_(m00mk@{Tn>LnX^Sp(%V;wgJ^#>Dlt) z_NqGwAbJb_mK-_Ig`2NnkH(p?fJPa8BMrAy`m)0AU~Gw_uL@wlLGxAQ-N4vtR(#iN z7q2T{gndiQ^CgJ&-q}uP&gYrumfV9zS;^M}*xd>{$=LmjeMVy2;Zb!yQQ+4Y{Ao@c zOxgP7oH&-+sQ;Z4)2Vg2Ymf!K(cINU5QTdk{znoGR=57>pW+egd;)(Vz)YX8NTt)_ S@pMK!nQnp0IX9dB-S`*d;Mq?A