(Using NASM on Ubuntu 7.10)

I'm messing with a simple linear transposition encryption program. It added 5 to each character in the string excluding the linefeed character. I thought I would jumble it a little more by make it add 1 the the first character 2 to the second and 3 to the third, up to 6 then start at one again.

Here is what I tried.

section .data
	msg:	db 'Message to be encrypted',0xa
	meglen:	equ $-msg

section .text
	global _start

_resetesi:

	mov	esi,1
	ret

_start:

	mov	eax,4	;Write origional String
	mov	ebx,1
	mov	ecx,msg
	mov	edx,meglen
	int	0x80
	
	mov	ebx,meglen	;Put the message in eax and the length in ebx
	dec	ebx;
	mov	eax,msg
	mov	esi,1
	

_eachchar:

	add	byte[eax], esi
	inc	eax
	inc	esi
	dec	ebx

	cmp	esi,6
	je	_resetesi
	cmp	ebx,0
	jne	_eachchar

	mov	eax,4	;Write encrypted string
	mov	ebx,1
	mov	ecx,msg
	mov	edx,meglen
	int	0x80
	
_exit:

	mov	eax,1
	mov	ebx,0
	int	0x80

When I try to compile I get the error:
encrypt.asm:29: error: mismatch in operand sizes

I tried using si instead of esi, but I still got the same error. I apologize if this question could be easily google'd, but I couldn't seem to find an explanation.

Thanks!

Ancient Dragon commented: Wow! Glad to see you actually read and understood the DaniWeb rules. Good going :) +21

Dani AI

Generated

NASM’s “mismatch in operand sizes” means the instruction’s operands are not the same width. Writing add byte [ptr], reg forces the memory operand to 8-bit, so the register must also be 8-bit (e.g., al, bl, cl, or dl). Using si or esi with a byte memory operand will always trigger this error. You can instead keep a small 8-bit step counter and add that to each byte.

Example loop that cycles 1..6 and skips the trailing LF by processing msglen-1 bytes. It uses distinct registers for pointer (EDI), counter (ECX), and the 8-bit step (BL):

section .data
  msg db 'Message to be encrypted', 10
  msglen      equ $ - msg
  msglen_nolf equ msglen - 1

section .text
; EDI -> msg, ECX = msglen_nolf, BL = 0
  mov  edi, msg
  mov  ecx, msglen_nolf
  xor  ebx, ebx           ; BL = 0

.loop:
  inc  bl                 ; 1..6
  cmp  bl, 7
  jne  .no_wrap
  mov  bl, 1
.no_wrap:
  mov  al, [edi]
  add  al, bl
  mov  [edi], al
  inc  edi
  dec  ecx
  jnz  .loop

Tip: if you want the 1..6 pattern to ignore newlines anywhere in the string, test al for 10 before the add, and only inc bl when you actually modify a byte.

For details on operand-size rules, see the NASM manual’s operand-size discussion (NASM docs) and Intel’s ADD reference (Intel SDM, ADD).

Recommended Answers

All 9 Replies

line 29: byte is a reserved word that means one byte and you are attepting to add a 16-bit register value to it. You will probably have to use a different general register to do it

mov edx,esi
add byte[eax], dl

But when you do that you might as well replace esi with edx everywhere in that loop to avoid repeated copying.

That got rid of the error. I just replaced esi with dl. I'm curious why you said to move esi to edx? Also could you explain a little about dl?

Thanks again

>>I'm curious why you said to move esi to edx?
esi is a 32-bit register and can only be copied to another 32-bit register.

>>Also could you explain a little about dl?
Its just an 8-bit register just like al. Only eax, ebx, ecx, edx contain 32-bit, 16-bit and 8-bit registers. And you have to use an 8-bit register to do anything with just one byte of memory.

>>Only eax, ebx, ecx, edx contain 32-bit, 16-bit and 8-bit registers.

OK, so would eax, ax and al all be the same register/memory. Can all three of those contain seperate values?

Thanks for working with me. :)

> OK, so would eax, ax and al all be the same register/memory.
Yes and no. Read on.

> Can all three of those contain seperate values?
Yes and no. Read on.

AL is the low-order byte of AX. AH is the high-order byte of AX. Thus, AX is a 16-bit value (composed of two eight-bit values).

Likewise, AX is the low-order word of EAX. You can swap the low- and high-order words of EAX using the ROL opcode, say: ROL EAX, 16 .

So, if you set AL to 07h and AH to 8Ah, then it is the same as setting AX to 8A07h.

Hope this helps.

Helped a lot!

So then, with the rotate code, you could do this: ROL EAX, 8Ah and ROR EAX, 07h Would EAX contain 07h8Ah?

Or does it not work like that?

Assuming EAX is already null

or ah, 7
or al, 8a

would give you that result

ROL SAL SHL and instructions to do bitwise shifts either left in this case or right using ROR RAR SHR.

Knowing the instruction set goes a long way to becoming an effective assembly programmer

Back when people had to count nanoseconds on older processors it actually made a difference how you used certain registers.

Nowdays, just say MOV AL, 7 or MOV AX, 78Ah --whichever is needed.

Like Tight_Coder_Ex said, make sure you get a good reference. ROL, RCL, etc. are woefully underused opcodes, but very powerful. Look them up.

Follow along:

mov ax, 78Ah  ; AH == 07h, AL == 8Ah; AX == 078Ah
rol ax, 4     ; AH == 78h, AL == A0h; AX == 78A0h
rol ax, 4     ; AH == 8Ah, AL == 07h; AX == 8A07h

Hope this helps.

Thanks a lot for the help guys! Still very confusing. I have only glanced at the Asm References thread, but if you guys have any suggestions for books or Web sites, let me know. I'm really struggling with finding references.

David

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.