非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

アセンブラ(20)

描画が実行できるようになりました。

実行例(長方形の描画)

void DirectDrawRectangle(HDC hdc, int x1, int y1, int w, int h, COLORREF color) {
    for (int x = x1; x < x1 + w; ++x) {
        SetPixel(hdc, x, y1, color);
        SetPixel(hdc, x, y1 + h, color);
    }
    for (int y = y1; y < y1 + h; ++y) {
        SetPixel(hdc, x1, y, color);
        SetPixel(hdc, x1 + w, y, color);
    }
}

これをコンパイルすると以下のようなアセンブリ言語のコードが得られます。

_Z19DirectDrawRectanglePiiiiim:
	movem.l #7964,-(%sp)
	move.l 36(%sp),%d5
	move.l 40(%sp),%d7
	move.l 44(%sp),%d3
	move.l 56(%sp),%d6
	move.l %d7,%d4
	move.l %d7,%a4
	add.l 48(%sp),%a4
	move.l %d3,%a3
	add.l 52(%sp),%a3
	lea _Z8SetPixelPiiim,%a5
.L147:
	cmp.l %a4,%d4
	jlt .L148
	lea _Z8SetPixelPiiim,%a5
.L149:
	cmp.l %a3,%d3
	jlt .L150
	movem.l (%sp)+,#14584
	rts
.L148:
	move.l %d6,-(%sp)
	move.l %d3,-(%sp)
	move.l %d4,-(%sp)
	move.l %d5,-(%sp)
	jsr (%a5)
	lea (12,%sp),%sp
	move.l %d6,(%sp)
	move.l %a3,-(%sp)
	move.l %d4,-(%sp)
	move.l %d5,-(%sp)
	jsr (%a5)
	addq.l #1,%d4
	lea (16,%sp),%sp
	jra .L147
.L150:
	move.l %d6,-(%sp)
	move.l %d3,-(%sp)
	move.l %d7,-(%sp)
	move.l %d5,-(%sp)
	jsr (%a5)
	lea (12,%sp),%sp
	move.l %d6,(%sp)
	move.l %d3,-(%sp)
	move.l %a4,-(%sp)
	move.l %d5,-(%sp)
	jsr (%a5)
	addq.l #1,%d3
	lea (16,%sp),%sp
	jra .L149
_Z8SetPixelPiiim:
	*setpixel
	rts

疑似関数「*setpixel」は関数「SetPixel」の本体の代わりに使えるものです。これを使って書き直しています。

実行例(塗りつぶした長方形の描画)

void DirectFillRectangle(HDC hdc, int x1, int y1, int w, int h, COLORREF color) {
    for (int y = y1; y < y1 + h; ++y) {
        for (int x = x1; x < x1 + w; ++x) {
            SetPixel(hdc, x, y, color);
        }
    }
}

これをコンパイルすると以下のようなアセンブリ言語のコードが得られます。

_Z19DirectFillRectanglePiiiiim:
	movem.l #7952,-(%sp)
	move.l 32(%sp),%d5
	move.l 36(%sp),%d3
	move.l %d3,%d6
	add.l 44(%sp),%d6
	move.l %d5,%d7
	add.l 40(%sp),%d7
	lea _Z8SetPixelPiiim,%a3
.L152:
	cmp.l %d6,%d3
	jlt .L155
	movem.l (%sp)+,#2296
	rts
.L153:
	move.l 48(%sp),-(%sp)
	move.l %d3,-(%sp)
	move.l %d4,-(%sp)
	move.l 40(%sp),-(%sp)
	jsr (%a3)
	addq.l #1,%d4
	lea (16,%sp),%sp
.L154:
	cmp.l %d7,%d4
	jlt .L153
	addq.l #1,%d3
	jra .L152
.L155:
	move.l %d5,%d4
	jra .L154
_Z8SetPixelPiiim:
	*setpixel
	rts

疑似関数「*setpixel」を使って書き直しています。

実行例(塗りつぶした長方形の描画・直線の描画を使うバージョン)

上記の実行例の速度を改善するため直線は直接描画するようにします。

void DirectFillRectangle_hline(HDC hdc, int x1, int y1, int w, int h, COLORREF color) {
    for (int y = y1; y < y1 + h; ++y) {
		DrawHLine(hdc, x1, y, w, color);
    }
}

DrawHLine 関数は以下のようになります。

void DrawHLine(HDC hdc, int x1, int y1, int w, COLORREF color) {
    HPEN hPen = CreatePen(PS_SOLID, 1, color);
    SelectObject(hdc, hPen);
    MoveToEx(hdc, x1, y1, NULL);
    LineTo(hdc, x1 + w, y1);
    DeleteObject(hPen);
}

これをコンパイルすると以下のようなアセンブリ言語のコードが得られます。

_Z25DirectFillRectangle_hlinePiiiiim:
	movem.l #6160,-(%sp)
	move.l 24(%sp),%d3
	move.l %d3,%d4
	add.l 32(%sp),%d4
	lea _Z9DrawHLinePiiiim,%a3
.L163:
	cmp.l %d4,%d3
	jlt .L164
	movem.l (%sp)+,#2072
	rts
.L164:
	move.l 36(%sp),-(%sp)
	move.l 32(%sp),-(%sp)
	move.l %d3,-(%sp)
	move.l 32(%sp),-(%sp)
	move.l 32(%sp),-(%sp)
	jsr (%a3)
	addq.l #1,%d3
	lea (20,%sp),%sp
	jra .L163
_Z9DrawHLinePiiiim:
	*hline
	rts

疑似関数「*hline」は関数「DrawHLine」の本体の代わりに使えるものです。これを使って書き直しています。