winchars

  • (by K, 2018.09.20)

(0) 概要

  • 要するにwin32のコンソールアプリでcharsをやる。
  • ちなみにあとでhelloもやりたい。

(1) とりあえず、これでいいんじゃないかな?

  • ソースコード「winchars.s」
        .file   "winchars.s"
        .text
        .def    _mainCRTStartup; .scl 2; .type 32; .endef
    _mainCRTStartup:
        pushl   %eax
        movl    %esp, %edi
        pushl   %eax
        movl    %esp, %esi
        movl    $32, %ebx
    L8:
        pushl   $-11
        call    _GetStdHandle@4
        pushl   $0
        pushl   %esi
        pushl   $1
        pushl   %edi
        pushl   %eax
        movl    %ebx, (%edi)
        call    _WriteFile@20
        cmpl    $10, %ebx
        je      L1
        incl    %ebx
        cmpl    $126, %ebx
        jle     L8
        movb    $10, %bl
        jmp     L8
    L1:
        popl    %eax
        popl    %eax
        xorl    %eax, %eax
        ret
  • これを以下のバッチファイルでアセンブル&リンク。
    c:\mingw\bin\gcc.exe -o winchars.o -c winchars.s
    ld -o winchars.exe -s -Bdynamic winchars.o --file-alignment 512 -lkernel32
  • これでできたwinchars.exeの内容
     offset   +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F  0123456789ABCDEF
    ---------------------------------------------------------------------------
    00000000  4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00  MZ..............  //windwosは最初のMZしか見ていないらしい.
      (重要ではないので中略)
    00000030  00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00  ................  //windowsは末尾の 00000080 しか見てないらしい(PEヘッダへのポインタ)
      (重要ではないので中略)
    00000080  50 45 00 00 4C 01 02 00 4B 9E 97 5B 00 00 00 00  PE..L...K..[....
    00000090  00 00 00 00 E0 00 0F 02 0B 01 02 38 00 02 00 00  ...........8....
    000000A0  00 02 00 00 00 00 00 00 00 10 00 00 00 10 00 00  ................
    000000B0  00 00 00 00 00 00 40 00 00 10 00 00 00 02 00 00  ......@.........
    000000C0  04 00 00 00 01 00 00 00 04 00 00 00 00 00 00 00  ................
    000000D0  00 30 00 00 00 04 00 00 82 7F 00 00 03 00 00 00  .0..............
    000000E0  00 00 20 00 00 10 00 00 00 00 10 00 00 10 00 00  .. .............
    000000F0  00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00  ................
    00000100  00 20 00 00 7C 00 00 00 00 00 00 00 00 00 00 00  . ..|...........
    00000110  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000120  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000130  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000140  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000150  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000160  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000170  00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00  .........text...
    00000180  60 00 00 00 00 10 00 00 00 02 00 00 00 04 00 00  `...............
    00000190  00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60  ............ ..`
    000001A0  2E 69 64 61 74 61 00 00 7C 00 00 00 00 20 00 00  .idata..|.... ..
    000001B0  00 02 00 00 00 06 00 00 00 00 00 00 00 00 00 00  ................
    000001C0  00 00 00 00 40 00 00 C0 00 00 00 00 00 00 00 00  ....@...........
      (重要ではないので中略)
    00000400  50 89 E7 50 89 E6 BB 20 00 00 00 6A F5 E8 2E 00  P..P... ...j....
    00000410  00 00 6A 00 56 6A 01 57 50 89 1F E8 28 00 00 00  ..j.Vj.WP...(...
    00000420  83 FB 0A 74 0A 43 83 FB 7E 7E E0 B3 0A EB DC 58  ...t.C..~~.....X
    00000430  58 31 C0 C3 90 90 90 90 90 90 90 90 90 90 90 90  X1..............
    00000440  FF 25 3C 20 40 00 90 90 FF 25 40 20 40 00 90 90  .%< @....%@ @...
    00000450  FF FF FF FF 00 00 00 00 FF FF FF FF 00 00 00 00  ................
      (重要ではないので中略)
    00000600  2C 20 00 00 00 00 00 00 00 00 00 00 6C 20 00 00  , ..........l ..
    00000610  3C 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00  < ..............
    00000620  00 00 00 00 00 00 00 00 00 00 00 00 48 20 00 00  ............H ..
    00000630  58 20 00 00 00 00 00 00 00 00 00 00 48 20 00 00  X ..........H ..
    00000640  58 20 00 00 00 00 00 00 84 01 47 65 74 53 74 64  X ........GetStd
    00000650  48 61 6E 64 6C 65 00 00 3B 03 57 72 69 74 65 46  Handle..;.WriteF
    00000660  69 6C 65 00 00 20 00 00 00 20 00 00 4B 45 52 4E  ile.. ... ..KERN
    00000670  45 4C 33 32 2E 64 6C 6C 00 00 00 00 00 00 00 00  EL32.dll........
      (重要ではないので中略)
    000007F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

(2) でもやっぱり小さくしたい

  • たかがcharsで2048バイトも使ってしまうというのは、やっぱりイライラします。
  • ということで、小さくしてみました。
  • 結論から言うと、656バイトにできました。
  • まずどうやってもヘッダサイズを512バイトよりも小さくはできませんでした。やろうとすると起動できなくなってしまうのです。無念。
  • しょうがないので、必要なセクションを1つにまとめて、そのセクションを切り詰めて144バイトまで減らしたわけです。そうやって656バイトを達成しています。
  • 以下はnaskでのソースコードです。リンカを使わずに直接.exeファイルを生成します。
    [FORMAT "BIN"]
    [INSTRSET "i486p"]
    [BITS 32]
    
    base	equ		0x400000
    
    ; MZヘッダ
    
        DB		"MZ"
        RESB	58
        DD		0x80
        RESB	64
    
    ; PEヘッダ
    
        DB		"PE", 0, 0
        DW		0x014c	; x86(32bit)
        DW		1	; セクション数
        DD		0, 0, 0
        DW		0xe0	; オプショナルヘッダのサイズ
        DW		0x0103
    
    ; オプショナルヘッダ
    
        DW		0x010b
        RESB	14
        DD		entry-base	; エントリポイント(RVA)
        RESB	8
    
        DD		base	; イメージベース
        DD		0x1000	; セクションアラインメント
        DD		512		; ファイルアラインメント(512から減らせない)
    
        DW		4, 0, 1, 0, 4, 0	; たぶんここは重要じゃない
        DD		0
    
        DD		0x2000	; ロードに必要なメモリサイズ
        DD		0x0200	; 総ヘッダサイズ
        RESB	4
        DW		3, 0	; コンソールアプリ
    
        DD		0x00200000
        DD		0x00001000
        DD		0x00100000
        DD		0x00001000
    
        DD		0
        DD		16
    
        DD		0, 0
        DD		idata-base, 0x007c
        RESB	8*14
    
    ; セクションヘッダ
    
        DB		".text", 0, 0, 0
        DD		txtsiz	; サイズ
        DD		0x00001000	; ロードアドレス(RVA)
        DD		txtsiz	; ファイルアラインで切り上げられたサイズ
        DD		0x0200	; ファイル内オフセット
        RESB	12
        DD		0x60000020
    
        RESB	0x200-$
    
        ORG		0x401000
    
    entry:
        PUSH	EAX
        MOV		EDI,ESP
        PUSH	EAX
        MOV		EBP,ESP
        MOV		BL,' '
        MOV		ESI,idata.iat
    l8:
        PUSH	-11
        CALL	[ESI+0]	; GetStdHandle
        PUSH	0
        PUSH	EBP
        PUSH	1
        PUSH	EDI
        PUSH	EAX
        MOV		[EDI],BL
        CALL	[ESI+4]	; WriteFile
        CMP		BL,10
        JE		l1
        INC		EBX
        CMP		BL,126
        JLE		l8
        MOV		BL,10
        JMP		l8
    l1:
        POP		EAX
        POP		EAX
        XOR		EAX,EAX
        RET
    
        ALIGNB	4
    
    idata:
        DD		0, 0, 0, .dllname-base, .iat-base
        DD		0, 0, 0, 0, 0	; ターミネータ―
    
    .iat:	; import address table
        DD		.iat0-base, .iat1-base, 0
    
    .iat0:
        DB		0x84, 0x01, "GetStdHandle", 0
    .iat1:
        DB		0x3b, 0x03, "WriteFile", 0
    .dllname:
        DB		"KERNEL32.dll", 0
    
    txtsiz	equ		$-$$

もし msvcrt.dll をつかってもいいのなら・・・

  • charsは609バイト
  • helloは606バイト

こめんと欄


コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-07-09 (火) 01:58:49 (74d)