1

I wanted to see if self-modifying code in assembly is possible, since .text is read-only I thought I could put the code in .data instead, I tried the code below.

section     .text
global      _start                            ;must be declared for linker (ld)

_start:                                       ;tell linker entry point

    mov al,3
    mov rbx,cont1                             ;store label cont1 in rbx so we can continue there
    mov cl,byte [dec_op]                      ;put the opcode of the dec instruction in cl
    mov byte [code],cl                        ;replace the inc instruction with a dec instruction
    jmp code                                  ;run the modified code
cont1:
    mov byte [dat1],al                        ;store away the changed value
    add byte [dat1],0x30                      ;turn the internal numeric value into an ascii digit
    mov eax,4                                 ;system call number (sys_write)
    mov ebx,1                                 ;stdout
    mov ecx,dat1                              ;location of data
    mov edx,2                                 ;length of data
    int 0x80                                  ;call kernel

    mov     eax,1                             ;system call number (sys_exit)
    int     0x80                              ;call kernel

section     .data

dat1        db 0,0xa                          ;location to store output
dec_op      dec al                            ;the dec instruction
code        inc al                            ;code to modify
            jmp rbx

The output of the above is

4

While I expected 2, since after modifying itself, it should have a decrease instruction instead of an increase instruction. What am I doing wrong?

I'm running debian sid 64-bit and I'm compiling with:

nasm -f elf64 sm.s
ld -s -o sm sm.o
Alice Ryhl
  • 3,574
  • 1
  • 18
  • 37
  • http://en.wikipedia.org/wiki/Self-modifying_code#Interaction_of_cache_and_self-modifying_code – Hans Passant Dec 28 '14 at 12:04
  • @HansPassant That makes sense, do you have any resources on the instructions required to syncronize the caches? – Alice Ryhl Dec 28 '14 at 12:08
  • you're doing thje self-modifying code in the correct form, you have a jmp after you do the modify, that's all that's needed to clear the prefetch. – Jasen Dec 28 '14 at 12:11

1 Answers1

4

it's because DEC AL takes 2 bytes

from a "listfile" produced by nasm (columns slightly condensed):

 26 00000000 000A     dat1        db 0,0xa                ;location to store output
 27 00000002 FEC8     dec_op      dec al                  ;the dec instruction
 28 00000004 FEC0     code        inc al                  ;code to modify
 29 00000006 FFE3                 jmp rbx

It can be seen that the first byte of both op-codes is identical, hence the confusion.

And this is the fix.

    mov cx,word [dec_op]                      ;put the opcode of the dec instruction in cl
    mov word [code],cx                        ;replace the inc instruction with a dec instruction
Jasen
  • 11,837
  • 2
  • 30
  • 48