0

質問 1:次のアセンブラ コードがあります。その目的は、入力文字列をループ処理し、遭遇するエスケープ文字 '%' の数をカウントすることです。

.globl sprinter

.data

.escape_string: .string "%"

.num_escape: .long 0

.num_characters: .long 0

.text

sprinter:
    pushl %ebp
    movl %esp,%ebp

    movl 8(%ebp),%ecx # %ecx = parameter 1

loop:
    cmpb $0, (%ecx) # if end of string reached
    jz exit
    cmpl $.escape_string,(%ecx) # if escape character found
    je increment
    back:
        incl .num_characters
        incl %ecx
        jmp loop

increment:
    incl .num_escape
    jmp back # jump to 'back'

exit:
    movl .num_escape, %eax # return num_escape

    popl %ebp
    ret

このアセンブリ コードは、次の C コードと共にコンパイルされます。

#include <stdio.h>
extern int sprinter (char* string);
int main (void)
{
    int n = sprinter("a %d string of some %s fashion!");
    printf("value: %d",n);
    return 0;
}

このコードを実行すると予想される出力はvalue: 2(文字列に 2 つの '%' 文字があるため) ですが、 が返されます。これはvalue: 0、次の行が失敗したことを意味します (カウンターがインクリメントされないため)。

cmpl $.escape_string,(%ecx) # if escape character found

文字列の比較に間違った方法を使用していますか? 外側のループは正常に機能し、.num_characters には文字列の文字数が正しく含まれています。文字列「hello」を「hello2」と比較する単純な C プログラムのアセンブリ コードを生成しました。これが関連するコードです。

.LC0:
    .string "hello"
.LC1:
    .string "hello2"

...
movl    $.LC0, -4(%ebp)
cmpl    $.LC1, -4(%ebp)

私が試したものと非常によく似ていますよね?

質問2。このコードは、アセンブリで記述された簡略化された sprintf 関数の一部です。これは、最初のパラメーターが結果の文字列であり、2 番目のパラメーターがフォーマットであることを意味します。あるレジスタの現在の位置から別のレジスタの現在の位置にバイト文字をコピーするにはどうすればよいですか? パラメータを 2 つのレジスタに割り当てたとします。

movl 8(%ebp),%edx # %edx = result-string
movl 12(%ebp),%ecx # %ecx = format-string

ループで次のことを試しました:

movb (%ecx), %al
movb %al, (%edx) # copy current character to current position in result register
incl %ecx
incl %edx

しかし、結果の文字列にはa(文字列の最初の文字) だけが含まれており、期待どおりの完全な文字列ではありません。

この比較の問題(質問1)が現在私を行き詰まらせているため、すべての助けに感謝します。

4

1 に答える 1

2

質問 1 に関しては、1 バイト文字を比較しているように見えるので、エスケープ文字をチェックするときは「cmp」を「cmpb」にする必要があります。また、キャラクターをレジスターにロードする必要があります。私は AT&T アセンブリにあまり詳しくないので、これが正しいことを願っています。

ループ前:

movb .escape_string, %al

比較:

cmpb %al, %(ecx)
于 2013-05-08T19:16:00.307 に答える