Archive for February, 2009

Converting assembly language to the Scheme/Lisp format

Saturday, February 28th, 2009

I have found another code generation bug – it is necessary to add +0 in front of negative numbers. The current emphasis is on “closing the loop” – where a Scheme system base can be built by Scheme itself.

The first step to closing the loop is done. The MASM assembly language line-oriented code has been converted into Scheme forms. As noted in previous posts, I have a translator for converting the Scheme forms to MASM code.

I’ve already used the nested list feature to insert debugging code into the Scheme assembly program. The nested list feature can also be exploited to provide a small amount of code refactoring – the next step.

Starter code for Lisp-style assembly code

Saturday, February 21st, 2009

I created the following list to get the assembly code generation started. This means another step toward an all-Lisp development environment.

The dot functions generate a symbol that starts with the “.” character, because the base interpreter does not allow the “.” character to start a symbol. The base interpreter will interpret, in that position, the “.” character as a single-character separator.

The “+” character in front of 0 is due to a deficiency – the code generator functions don’t handle the special numeric 0 encoding. It also shows a way to handle arbitrary expressions that must start with digits.

The symbol textequ must also be associated with the same procedure that equ and label use.

      (set! code
        (list
          (list (dot386))
          (list (dotmodel)  'flat)

          '(textequ ExitProcess <_ExitProcess@4>)
          '(extern ExitProcess:near)

          (list (dotcode))

          '(label _start near)
          '(push +0)
          '(call ExitProcess)

          (list (dotdata))

          '(end _start)))

Repeatedly applying the translate function to the list items yields

.386
.model flat
ExitProcess textequ <_ExitProcess@4>
extern ExitProcess:near
.code
_start label near
push +0
call ExitProcess
.data
end _start

When coupled with Microsoft’s Win32 API library (such as the one provided for VC++), the above code will assemble, link, and run in a 32-bit MASM environment.

Macro assembly, part 2

Saturday, February 14th, 2009

If you look carefully, you can see the first attempt to create macros actually treats the “macro” as a command to generate code.

As a second attempt, we can treat a macro as a command to insert instructions. We can envision the result of the insertion as creating a nested list of instructions. Unfortunately, the label syntax means we can’t just nest it verbatim. The nested instruction sequence

((op1 a)
  (label1
    (op2 b)
    (op3 c))
  (op4))

will actually look like

((op1 a)
  (label1 (op2 b) (op3 c))
  (op4))

where label1 is interpreted as a machine instruction called label1.

After letting the issue sit for a while, I have chosen to eliminate the special label notation. We can simply use (equ label1 $) or (label label1 near) to generate an equivalent MASM instruction. And then, instead of using

'((op1 a b)
  (macro mac1)
  (op2 a b))

we can use

(list
  '(op1 a b)
  mac1
  '(op2 a b))

to nest instruction sequences.

Well, now I can see that quasi-quoting (aka backquoting) would be more elegant. However, the quasi-quoting is going to have to wait.