2016-08-25 1 views
-1

Ich programmiere in Assembler und ich habe einen Hilfspuffer erstellt, um vorübergehend einige Zeichen zu speichern und sie dann in eine Datei zu schreiben. Die Sache ist, dass ich den Hilfspuffer mehrere Male benutzen muss, also muss ich es säubern/wiederherstellen und ich weiß nicht, wie man das erreicht.Wie lösche ich einen Puffer in Assembly?

Ich benutze i386 Architektur mit Linux.

PD: Ich habe vergessen, das ist, wie ich den Puffer erklärt haben:

section .bss   
     auxBuffer resb 1000 
+0

nicht anders als in jeder anderen Sprache. –

+6

Sie suchen nach 'rep stosb'. Können Sie den gleichen Puffer nicht erneut verwenden, ohne ihn zu löschen? Wenn Sie den vorherigen Inhalt bereits verwenden, warum müssen Sie ihn dann löschen? –

+1

@DanielKamilKozar Ich muss den Inhalt des Puffers in eine Datei schreiben, ich denke nur, wenn ich es mehrmals benutze, ohne es zu löschen, kann ich es nicht füllen und einen Überlauf bekommen? – JamesFred

Antwort

2

Sie klar ein Puffer, um es durch das Schreiben.
Offensichtlich ist ein Speicherort im Speicher nie wirklich leer, daher bedeutet das Löschen eines Puffers, dass er mit Nullen gefüllt wird.
Es gibt nichts, was Sie davon abhält, es mit 0xCAFEBABE Hexadezimalwerten zu füllen, aber Nullen ist die Standardkonvention.

mov dword ptr [buffer],0 
mov dword ptr [buffer+4],0 
mov ...    +8],0 
.... 

Offensichtlich ist dies eine alberne Art, einen Puffer zu löschen. Wenn der Puffer 40.000 Byte wäre, würden Sie 10.000 Anweisungen benötigen; möglich, aber verschwenderisch.

Stattdessen schreiben Sie eine Schleife und verwenden Sie einen Zähler, um zu verfolgen, was Sie bisher geschrieben haben.

mov ecx,10000  //10000 x 4 = 40.000 bytes 
lea edx,[buffer]  //point edx to the start of the block to be cleared. 
xor eax,eax   //xor reg,reg is the same as mov reg,0, but faster. 
@loop: 
mov [edx+ecx*4],eax //fill the buffer starting at the end. 
dec ecx    //decrease the counter; also moving the destination. 
jnz @loop   //if ecx <> 0 (Non-Zero) then repeat. 
ret     //we are done, return. 

ecx erfüllt zwei Funktionen als Zähler und als Zeiger in den Puffer.
Beachten Sie, dass xor eax,eax die Standardmethode ist, ein Register auf Null zu setzen. Es ist sowohl kürzer als mov eax,0 und schneller, weil die CPU fest verdrahtet ist, um der ersteren Anweisung bevorzugte Behandlung zu geben.
Es gibt jedoch eine noch kürzere Möglichkeit, dies zu tun.
x86 hat sogenannte String-Anweisungen, die eine rep (repeat) prefix akzeptieren.
Wenn so vorangestellt wird, wird die Anweisung ecx mal ausgeführt.

push edi   //on Windows edi is non-volatile (callee-save), so save it. 
lea edi,[buffer] //edi is the start of the buffer. 
xor eax,eax  //fill the buffer with zeros. 
mov ecx,10000  
rep stosd   //store string with 10000 dwords = 40000 bytes. 
pop edi   //restore edi to its previous value. 
ret    //return. 

stosd (s ̲ t ̲ o ̲ re s ̲ Tring pro d ̲ Wort) verwendet edi als D ̲ estination und ecx als C ̲ ounter eax und als Quelle.
Beachten Sie, dass stosd eine komplexe Anweisung ist. Moderne x86-CPUs arbeiten schneller mit einfachen Anweisungen und oft funktioniert eine optimierte (!) Version des zweiten Codeausschnitts schneller als eine einfache Verwendung von rep stosd.
rep stosd verschiebt sich standardmäßig unter Windows/Linux. Sie können die CPU so einrichten, dass sie rückwärts läuft, aber dann müssen Sie die Richtungseinstellung danach wiederherstellen.

Unter Windows eax, ecx und edx sind flüchtig und können nach Belieben verändert werden. Alle anderen Register müssen zwischen den Anrufen erhalten bleiben.

+0

Um eine Vorstellung von dem optimierten Assembly-Code zu erhalten, der zum Löschen eines Puffers verwendet werden würde, kompilieren Sie eine Scratch-C-Anwendung, die die 'memset'-Funktion aufruft, und untersuchen dann die Disassemblierung. Beachten Sie jedoch, dass dies nicht wirklich eine Operation ist, die hoch optimiert werden muss. Es macht mehr Sinn, für die Größe als für die Geschwindigkeit zu optimieren, so dass die String-Anweisungen eine ziemlich gute Wette sind, die sowohl relativ schnell als auch extrem kurz ist (byteweise). –

Verwandte Themen