2016-06-25 17 views
1

私のコードで間違いを見つけたことに感謝します。私はバッファにアドレスを取る関数を書くことになっていました。文字l、数値n、そして0の値と1の2つの値しか取ることができない変数を増やします。 もし変数が0の場合、関数は同じ文字をn回繰り返します。変数が1の場合、関数は後続の文字列、たとえば "abcd ...."(後続のアスキー文字)を返す必要があります。 文字lは、文字列で始まる文字を決定します。私はDDDを使用してみましたアセンブリコード - エラーが見つかりません

が、それは問題がライン MOVL%ECX、(%のEDX) であると私は、レジスタEDXとECXで誤った値があることを知っていることを私に伝えます。 まだ、私は何が間違っているのか、それを修正する方法を理解できません。私は助けに非常に感謝しています。

#include <stdio.h> 
#include <stdlib.h> 
extern char * generate_str(char * s, int c, int n, int inc); 

int main() 
{ 
    char s[100] = "something"; 
    char c = 'a'; 
    int n = 5; 
    int inc = 0; 
    printf("String %s\n", generate_str(s, (int)c, n, inc)); 
} 

アセンブリコード:

.data 
character: .int 0 

# char -> 1 
# int -> 4 
# arguments: char * s, int c, int n, int inc 

.equ bufor,8 
.equ c,12 
.equ n,16 
.equ inc,20 
#eax, ebx, ecx, edx 

.text 
.type generate_str, @function 
.global generate_str 

generate_str: 

    PUSHL %ebp   #prolog of the function 
    MOVL %esp, %ebp 
    MOVL inc(%esp), %eax #copy variable inc into eax 
    MOVL n(%esp), %ebx #copy variable n into ebx 
    PUSHL %ecx   #save contents of ecx 
    MOVL c(%esp), %ecx #copy variable c into ecx temporarily 
    MOVL %ecx, character #copy variable c into reserved memory called character 
    POPL %ecx    #restore contents of c 
    MOVL bufor(%esp), %edx #copy addres of a buffer into edx 

    CMP $0, %eax # eax > 0 ? #is inc variable 0 or 1 
    JA one     #if it is 1, go to line "one" 
    MOVL %ebx, %ecx   %copy value of variable n into ecx, it tells how many letters should be placed in the buffer 
p: 
    PUSHL %ecx    #save contents of ecx 
    MOVL character, %ecx  #copy character into ecx 
    MOVL %ecx, (%edx)   #copy character into the place in the memory which address is given in edx 
    POPL %ecx     #restore contents of ecx 
    ADDL $4, %edx    #increase value of edx by 4, so we move forwards in the memory to save another letter there 
    loop p     #loop until ecx is 0 
    jmp end     #jump to the final part of the function 

one:       #if the value of inc is 1 then do another loop 
    PUSHL %ecx    #save ecx and use this register to copy character into the place in memory which address is in the edx registry 
    MOVL character, %ecx 
    MOVL %ecx, (%edx) 
    POPL %ecx 
    ADDL $1, character  #increase ascii character by 1 
    ADDL $4, %edx    #move in memory by 4 bytes so we can save the next letter 
    loop one     #continue loop until ecx is zero 
    jmp end 

end: 
    MOVL %edx, %eax   #copy address of the final string into eax 
    movl %ebp,%esp   #restore registers 
    popl %ebp 
RET 
+1

'MOVL bufor(%のESP)、%のedx'多分あなたは' LEAL bufor(%のespを意味を使用するバージョン)、%edx'。あなたのコードを適切にコメントしなかったので、伝えにくいです。また、明らかに 'ddd'を使うことができるので、コードをシングルステップ実行して、どこが間違っているかを確認してください。 PS: 'ebx'は呼び出し先保存レジスタです。 – Jester

+0

コードにコメントを追加しました。どのようにdddの1つのステップですか? 「ステップ」を押すたびに、プログラムが実行されないことがわかります。プログラムを実行するたびに、「ステップ」を押す前に終了します。 – Joanna

+0

ブレークポイントは、ファンクションの開始時や任意の場所に置くことができます。その後、そこからシングルステップを実行できます。ええ、 'コピーアドレス'には 'mov 'ではなく' lea'を使う必要があります。 – Jester

答えて

0

はあなたのアドバイスをいただき、ありがとうございます。 DDDはその仕事をしました。ここに訂正されたコードがあります。正直言って、次のcharを挿入するはずのアドレスを増やしていたとき(なぜなら、intに変換されていたため)、$ 4の代わりに$ 1を追加することになっていたのはなぜか分かりません。

#include <stdio.h> 
#include <stdlib.h> 
extern char * generate_str(char * s, int c, int n, int inc); 

int main() 
{ 
    char s[100] = "cos tam"; 
    char c = 'a'; 
    int n = 5; 
    int inc = 0; 
    printf("String %s\n", (char*) generate_str(s, (int)c, n, inc)); 

} 

アセンブリコード:

#dane 
.data 
character: .int 0 

# char -> 1 
# int -> 4 
# arguments: char * s, int c, int n, int inc 

.equ bufor,8 
.equ c,12 
.equ n,16 
.equ inc,20 
#eax, ebx, ecx, edx 

.text 
.type generate_str, @function 
.global generate_str 

generate_str: 
    PUSHL %ebp 
    MOVL %esp, %ebp 
    MOVL inc(%esp), %eax 
    MOVL n(%esp), %ecx 
    MOVL c(%esp), %ebx 
    MOVL bufor(%esp), %edx 
    PUSHL %ebx  

    CMP $0, %eax 
    JA one 
p: 
    MOVL %ebx, (%edx) 
    ADDL $1, %edx 
    loop p 
    ADDL $0, %edx 
    jmp end 

one: 
    MOVL %ebx, (%edx) 
    ADDL $1, %ebx 
    ADDL $1, %edx 
    loop one  
    ADDL $0, %edx 
    jmp end 

end: 
    MOVL bufor(%esp), %edx 
    MOVL %edx, %eax 
    movl %ebp,%esp 
    popl %ebx 
    popl %ebp 
    RET 

、変数

#dane 
.data 
letter: .int 0 

# char -> 1 
# int -> 4 
# arguments: char * s, int c, int n, int inc 

.equ bufor,8 
.equ c,12 
.equ n,16 
.equ inc,20 
#eax, ebx, ecx, edx 

.text 
.type generate_str, @function 
.global generate_str 

generate_str: 
    PUSHL %ebp 
    MOVL %esp, %ebp 
    MOVL inc(%esp), %eax 
    MOVL n(%esp), %ecx 
    MOVL c(%esp), letter 
    MOVL bufor(%esp), %edx 
    PUSHL %ebx 

    CMP $0, %eax 
    JA one 
p: 
    MOVL letter, %edi 
    MOVL %edi, (%edx) 
    ADDL $1, %edx 
    loop p 
    jmp end 

one: 
    MOVL %ebx, (%edx) 
    ADDL $1, %ebx 
    ADDL $1, %edx 
    loop one 
    ADDL $0, %edx 
    jmp end 

end: 
     MOVL bufor(%esp), %edx 
     MOVL %edx, %eax 
     MOVL %ebp,%esp 
     popl %ebx 
     popl %ebp 
     RET 
+0

*なぜ私は次のcharを挿入するはずのアドレスを増やしていたときに$ 4の代わりに$ 1を追加することになっていたのかを理解しています。文字列はバイトの配列です。メモリ内では、各要素は1バイトです。もちろん、オンザフライでintに変換することはできますが、*メモリ*では、各 'char'は1バイトです。 –

+0

呼び出し元の '%ebx'がまだ破壊されているように見えるので、より複雑な呼び出し関数から使用すると、コードがクラッシュする可能性があります。 http://stackoverflow.com/questions/8335582/why-does-ia-32-have-a-non-intuitive-caller-and-callee-register-saving-conventionを参照してください。また、[x86 tag wiki](http://stackoverflow.com/tags/x86/info) –

+0

私はPUSHL%ebxとPOPL%ebxを追加しました。今はどう? – Joanna

関連する問題