質問 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)が現在私を行き詰まらせているため、すべての助けに感謝します。