error A2070 при переносе байта из памяти в регистр

Тема в разделе "WASM.BEGINNERS", создана пользователем alexandersivak, 1 ноя 2020.

Метки:
  1. alexandersivak

    alexandersivak New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2020
    Сообщения:
    10
    Вот, собственно, код
    Код (Text):
    1. remove_spaces proc string:LPSTR
    2. ; здесь тоже есть код
    3.         remove:
    4.             mov BX,SI
    5.             mov al,string[EBX+1]; error A2070
    6.             mov string[EBX],al; error A2070
    7.             inc BX
    8.             cmp BX,cntr
    9.             jge change_length
    10.             jmp remove
    11.            
    12.                 change_length:
    13.                     mov string[EBX],0
    14.                     sub cntr,1
    15.                     jmp find_space
    16. quit:  
    17.     ret
    18.  
    19. remove_spaces endp
    Как поправить?
     
  2. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Попробуйте byte ptr
    Код (ASM):
    1. mov al, byte ptr string[EBX+1]
     
    alexandersivak нравится это.
  3. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Использовать например 32-битный указатель, а не инициализировать чем попало младшие 16 бит ebx и надеяться, что куда-то попадешь.
     
  4. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    f13nd, справедливости ради, там выше есть какой-то код (по словам ТСа). Может, там и обнуляется.
     
  5. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Чтобы такой фокус сработал, надо чтобы адреса в обоих регистрах были либо в образе (в пределах 64кб), либо в одном буфере (тоже в пределах 64кб). Заподозрить какую-то вундервафельную оптимизацию я не могу во-первых потому что пересылка из 16-бит регистра в регистр на 1 байт длиннее, во-вторых учитывая другие сообщения персонажа. А ошибка у новичков распространенная, когда начитаются книжек про ассемблер из времен молодости Пугачевой (их видимо больше написано) и берутся за 32бит.
     
    sl0n, M0rg0t и Mikl___ нравится это.
  6. alexandersivak

    alexandersivak New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2020
    Сообщения:
    10
    Код (Text):
    1. remove_spaces proc string:LPSTR
    2.     invoke lstrlen,string
    3.     cmp eax,0
    4.     je quit
    5.    
    6.     mov ESI,00000000
    7.     mov EBX,00000000
    8.     mov cntr,ax
    9.     sub cntr,1
    10.    
    11. find_space:
    12.     mov edx,[ebp+8]; load an address of string
    13.     mov eax,[edx+esi]; dereference a symbol
    14.     cmp al,' '
    15.     je remove
    16.     inc SI
    17.     cmp SI,cntr; is the symbol the last character?
    18.     jge quit
    19.     jmp find_space
    20.    
    21.         remove:
    22.             mov ebx,esi
    23.         R1:
    24.             mov al,[edx+ebx+1]; load '1' given string ' 1'
    25.             mov [edx+ebx],al; replace current symbol by the next symbol
    26.             inc BX
    27.             cmp BX,cntr
    28.             jge change_length
    29.             jmp R1
    30.            
    31.                 change_length:
    32.                     mov byte ptr[edx+ebx],0; decrease a length of string
    33.                     sub cntr,1
    34.                     jmp find_space
    35. quit:  
    36.     ret
    37.  
    38. remove_spaces endp
    Так?
     
  7. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Ах вон оно как, esi и ebx индексами оказались, а string метка. В принципе так, но еще бы поменьше тяготения к 16-бит регистрам. Это увеличение длины инструкции на 1 байт префикса, пользы не приносит, только увеличивает объем кода.

    Сравнение регистра с нулем:
    Код (ASM):
    1. cmp eax,0
    обычно принято делать так (на 1 байт дешевле):
    Код (ASM):
    1. test eax,eax
    Помещение нуля в регистр:
    Код (ASM):
    1. mov ESI,00000000
    2. mov EBX,00000000
    по той же причине предпочтительней так делать:
    Код (ASM):
    1. xor esi,esi
    2. xor ebx,ebx
    Ну и регистр ecx после вызова апи никак не используется, вместо него переменная cntr. Можно в регистре значение хранить.
    --- Сообщение объединено, 4 ноя 2020 ---
    Ну и если хочется повыёживаться оптимизаторством, то удаление всех пробелов из строки можно так реализовать (синтаксис fasm):
    Код (ASM):
    1. proc remove_spaces pszString
    2.             pushad
    3.                 xor eax,eax
    4.                 mov esi,[pszString]
    5.                 mov edi,esi
    6.                 .next:
    7.                 lodsb
    8.                 test eax,eax
    9.                 je .exit
    10.                 cmp eax,' '
    11.                 je .next
    12.                 stosb
    13.                 jmp .next
    14.                 .exit:
    15.                 stosb
    16.             popad
    17.             ret
    18. endp
     
    youneuoy нравится это.