Вот, собственно, код Код (Text): remove_spaces proc string:LPSTR ; здесь тоже есть код remove: mov BX,SI mov al,string[EBX+1]; error A2070 mov string[EBX],al; error A2070 inc BX cmp BX,cntr jge change_length jmp remove change_length: mov string[EBX],0 sub cntr,1 jmp find_space quit: ret remove_spaces endp Как поправить?
Использовать например 32-битный указатель, а не инициализировать чем попало младшие 16 бит ebx и надеяться, что куда-то попадешь.
Чтобы такой фокус сработал, надо чтобы адреса в обоих регистрах были либо в образе (в пределах 64кб), либо в одном буфере (тоже в пределах 64кб). Заподозрить какую-то вундервафельную оптимизацию я не могу во-первых потому что пересылка из 16-бит регистра в регистр на 1 байт длиннее, во-вторых учитывая другие сообщения персонажа. А ошибка у новичков распространенная, когда начитаются книжек про ассемблер из времен молодости Пугачевой (их видимо больше написано) и берутся за 32бит.
Код (Text): remove_spaces proc string:LPSTR invoke lstrlen,string cmp eax,0 je quit mov ESI,00000000 mov EBX,00000000 mov cntr,ax sub cntr,1 find_space: mov edx,[ebp+8]; load an address of string mov eax,[edx+esi]; dereference a symbol cmp al,' ' je remove inc SI cmp SI,cntr; is the symbol the last character? jge quit jmp find_space remove: mov ebx,esi R1: mov al,[edx+ebx+1]; load '1' given string ' 1' mov [edx+ebx],al; replace current symbol by the next symbol inc BX cmp BX,cntr jge change_length jmp R1 change_length: mov byte ptr[edx+ebx],0; decrease a length of string sub cntr,1 jmp find_space quit: ret remove_spaces endp Так?
Ах вон оно как, esi и ebx индексами оказались, а string метка. В принципе так, но еще бы поменьше тяготения к 16-бит регистрам. Это увеличение длины инструкции на 1 байт префикса, пользы не приносит, только увеличивает объем кода. Сравнение регистра с нулем: Код (ASM): cmp eax,0 обычно принято делать так (на 1 байт дешевле): Код (ASM): test eax,eax Помещение нуля в регистр: Код (ASM): mov ESI,00000000 mov EBX,00000000 по той же причине предпочтительней так делать: Код (ASM): xor esi,esi xor ebx,ebx Ну и регистр ecx после вызова апи никак не используется, вместо него переменная cntr. Можно в регистре значение хранить. --- Сообщение объединено, 4 ноя 2020 --- Ну и если хочется повыёживаться оптимизаторством, то удаление всех пробелов из строки можно так реализовать (синтаксис fasm): Код (ASM): proc remove_spaces pszString pushad xor eax,eax mov esi,[pszString] mov edi,esi .next: lodsb test eax,eax je .exit cmp eax,' ' je .next stosb jmp .next .exit: stosb popad ret endp