fork download
  1. global _start
  2.  
  3. section .data
  4.  
  5. section .text
  6.  
  7. ; 前提として起動時のレジスタは eip/espを除き 0x00000000、
  8. ; espはスタックの先頭を指している
  9.  
  10. ; Linuxシステムコール用にレジスタを準備
  11. ; system call : int 80h : write[eax=4](ebx=1, ecx=esp, edx=1)
  12. inc ebx ; 43 C
  13. inc edx ; 42 B
  14.  
  15. L_loop1:
  16. ; 出力文字列はスタックに置き、ecx=espを設定する。
  17. ; 即値pushは 4バイトのリトルエンディアンで配置されるため、
  18. ; メモリ上は 0x36 0x00 0x00 0x00 となる。0x36 は 文字'$'
  19. push 36 ; 6A24 j$
  20.  
  21. ; esiレジスタにステップ増分(本来は+2)の半分を持たせる。
  22. inc esi ; 46 F
  23.  
  24. ; ecxが0だとjecxz(E3xx)が使えないためとりあえず1を入れる。
  25. ; 以降、E3xxは有効文字化するためのダミーOP
  26. inc ecx ; 41 A
  27. db 0xe3,0x81 ; E381 ぉ (E38189)
  28.  
  29. ; 目的は ecxにespを入れることだが、直接movするOPは
  30. ; 文字コード的に使用できないため、ebpを経由する。
  31. mov ebp, esp ; 89E5 嗇 (E59787)
  32. xchg eax, edi ; 97
  33. ; 純粋に xchg ecx, ebp と書くと(87E9)にアセンブルされないため直接書く
  34. db 0x87, 0xe9 ; 87E9 雰 (E99BB0)
  35. wait ; 9B
  36.  
  37. L_loop2:
  38. ; eax = 4 だが、直接0x04が表現できないため、0xE9-0xE5 で入れる
  39. ; ASCIIコード内でも問題ないが、ジャンプ命令の位置あわせのため多バイト文字を使用している
  40. mov al, 0xE9 ; B0E9 鐐 (E99090)
  41. db 0x90,0x90 ; 9090
  42. sub al, 0xE5 ; 2CE5 ,吐 (E59090)
  43. db 0x90,0x90 ; 9090
  44.  
  45. ; システムコール int80h 起動
  46. ; CD80を表現できる文字コードは無く代替するOPも無いため、
  47. ; Unicode文字リテラルで記述 \U340。ただし後続の文字が英数ではないことが必須。
  48. int 0x80 ; CD80 \U340
  49.  
  50. ; スタックから現在の文字コードをediレジスタに取得
  51. pop edi ; 5F _
  52. db 0xe3,0x81 ; E381 き (E3818D)
  53. ; 加算後の文字コードを計算。ここで*2しているため、前述のステップ増分は+1で済む
  54. lea edi,[edi+esi*2] ; 8D2C3F <w
  55. db 0xe3,0x81 ; E381 し (E38197)
  56. xchg eax, edi ; 97
  57. ; 加算後の文字コードをスタックに戻す
  58. push eax ; 50 P
  59.  
  60. ; 1週終了判定('t'=116を越えると1週終わり) esp=ecxなので[ecx]で判定する。
  61. db 0xe3,0x82 ; E382 む (E38280)
  62. cmp byte [ecx], 118 ; 803976 9v
  63. jc L_loop2 ; 72xx r在 (E59CA8)
  64.  
  65. ; 有効文字化のダミーのため意味はなし
  66. pushfd ; 9C
  67.  
  68.  
  69. ; 終了条件 文字コード=132(0x84)
  70. ; 36,38,40,42,44,46,48,50, ... ,110,112,114,116,[118]
  71. ; 36,40,44,48,52,56,60,64, ... ,104,108,112,116,[120]
  72. ; 36,42,48,54,60,66,72,78,84,90,96,102,108,114,[120]
  73. ; 36,44,52,60,68,76,84,92,100,108,116,[124]
  74. ; 36,46,56,66,76,86,96,106,116,[126]
  75. ; 36,48,60,72,84,96,108,[120]
  76. ; 36,50,64,78,92,106,[120]
  77. ; 36,52,68,84,100,116,[132]
  78.  
  79. ; この時点でeaxに加算後の文字コードを持っているためalレジスタで判定
  80. ; 0x7BのANDを取り、0の場合に終了とする。
  81. ; 0x7BとANDを取って0になるのは 0,4,128,132のみのため、al=132の場合に終了となる。
  82. test al,0x7b ; A87B {
  83.  
  84. db 0xe3,0x81,0x9B ; せ (E3819B)
  85. jnz L_loop1 ; uё (D191)
  86. db 0x91
  87.  
  88.  
  89. ; ここまで
  90. ; your code goes here
  91. je exit
  92.  
  93. exit:
  94. mov eax, 01h ; exit()
  95. xor ebx, ebx ; errno
  96. int 80h
  97.  
  98.  
Success #stdin #stdout 0s 96KB
stdin
Standard input is empty
stdout
$&(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlnprt$(,048<@DHLPTX\`dhlpt$*06<BHNTZ`flr$,4<DLT\dlt$.8BLV`jt$0<HT`l$2@N\j$4DTdt