ඉන්ටෙල් 8086 CPU එකක් අනුකරණය කරන්න


160

සටහන: පිළිතුරු කිහිපයක් පැමිණ ඇත. අළුත් පිළිතුරු ද සලකා බලන්න.


මෙම 8086 ඉන්ටෙල් ප්රථම x86 ප්රොසෙසරය වේ. ඔබේ කාර්යය වන්නේ ඒ සඳහා ඉමුලේටරයක් ​​ලිවීමයි. මෙය සාපේක්ෂව දියුණු බැවින්, එය ලීටරයක් ​​සීමා කිරීමට මට අවශ්‍යය:

  • ක්‍රියාත්මක කළ යුත්තේ පහත දැක්වෙන ඔප්කෝඩ් පමණි:
    • mov, push, pop, xchg
    • එකතු කරන්න, adc, sub, sbb, cmp, සහ, හෝ, xor
    • inc, dec
    • අමතන්න, ret, jmp
    • jb, jz, jbe, js, jnb, jnz, jnbe, jns
    • stc, clc
    • hlt, නැත
  • මෙහි ප්‍රති result ලයක් ලෙස, ඔබට අවශ්‍ය වන්නේ රැගෙන යාම, බිංදුව සහ සලකුණු කොඩි පමණි
  • කොටස් ක්‍රියාත්මක නොකරන්න. උපකල්පනය කරන්න cs = ds = ss = 0.
  • උපසර්ග නැත
  • කිසිදු ආකාරයක බාධා කිරීම් හෝ වරාය IO නොමැත
  • නූල් කාර්යයන් නොමැත
  • බයිට් දෙකක ඔප්කෝඩ් නොමැත (0F ..)
  • පාවෙන ලක්ෂ්‍ය අංක ගණිතයක් නොමැත
  • (පැහැදිලිවම) බිට් 32 දේවල් නැත, sse, mmx, ... 1979 දී මෙතෙක් සොයාගෙන නැති කිසිවක්
  • ඔබට චක්‍ර ගණන් කිරීමට හෝ වේලාවක් කිරීමට අවශ්‍ය නැත

ip = 0සහ ආරම්භ කරන්න sp = 100h.


ආදානය: ඔබේ ඉමුලේටරය ඔබ කැමති ඕනෑම ආකාරයක ද්විමය වැඩසටහනක් ආදානය ලෙස ගත යුතුය (ගොනුවෙන් කියවන්න, පූර්ව නිශ්චිත අරාව, ...) එය 0 ලිපිනයට මතකයට පටවන්න.

ප්‍රතිදානය: වීඩියෝ RAM පැය 8000 ලිපිනයෙන් ආරම්භ වේ, සෑම බයිටයක්ම එක් (ASCII-) අක්ෂරයකි. කොන්සෝලය සඳහා 80x25 තිරයක් අනුකරණය කරන්න. ශුන්‍ය බයිට් අවකාශය මෙන් සලකන්න.

උදාහරණයක්:

08000   2E 2E 2E 2E 2E 2E 2E 2E 2E 00 00 00 00 00 00 00   ................
08010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
08020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
08030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
08040   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
08050   48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 00 00   Hello,.world!...

සටහන: මෙය සැබෑ වීඩියෝ මාදිලියට ඉතා සමාන වන අතර එය සාමාන්‍යයෙන් 0xB8000 වන අතර වර්ණ සඳහා අක්ෂරයකට තවත් බයිට් එකක් ඇත.

ජයග්‍රාහී නිර්ණායක:

  • ඉහත සඳහන් සියලු උපදෙස් ක්‍රියාත්මක කළ යුතුය
  • මම නිසි ලෙස ක්‍රියාත්මක විය යුතු නොගැලපෙන පරීක්ෂණ වැඩසටහනක් ( සබැඳිය , නාස් ප්‍රභවය ) සෑදුවෙමි . එය ප්‍රතිදානය කරයි

    .........                                                                       
    Hello, world!                                                                   
    0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 
    
    
    ################################################################################
    ##                                                                            ##
    ##  0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987                          ##
    ##                                                                            ##
    ##  0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400     ##
    ##                                                                            ##
    ##  2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97    ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ##                                                                            ##
    ################################################################################
    
  • මෙය කෝඩ්ගෝල්ෆ් විය යුතුදැයි මට විශ්වාස නැත; එය එක්තරා ආකාරයක අසීරු කටයුත්තකි, එබැවින් ඕනෑම ඉදිරිපත් කිරීමක් කෙසේ හෝ බොහෝ ඉහළ නැංවීම් දිනා ගනු ඇත. කරුණාකර අදහස් දක්වන්න.

මෙම කාර්යය සඳහා ඔබට උදව් කිරීමට සබැඳි කිහිපයක් මෙන්න:

මෙම වේදිකාවට මගේ පළමු පිවිසුම මෙයයි. කිසියම් වැරැද්දක් ඇත්නම්, කරුණාකර ඒවා පෙන්වා දෙන්න; මට විස්තරයක් මග හැරුනේ නම්, අහන්න.


5
මට වඩා බොහෝ දියුණුයි, නමුත් මෙම ප්‍රශ්නයට පිළිතුරු දැකීමට මම ඉතා උනන්දුවෙන් සිටිමි, එය හරියටම මා වඩාත් උනන්දුවක් දක්වන දේවල් වර්ගයකි! මට විශේෂයෙන් මැසොස්ටික් බවක් දැනේ නම් මට පසුව එය බිඳ දැමිය හැකිය ...
ක්‍රිස් බ්‍රවුන්

3
H ක්‍රිස්බ්‍රවුන් මැසොකිස්ටික් වීම වාසනාවකි! මම දැනට මගේ 8086 80386 බවට හරවන අතර මේ වන විට මෙම ව්‍යාපෘතියෙන් බොහෝ දේ ඉගෙන ගෙන ඇත්තෙමි .
පිටපත් කරන්න

2
+1 + ප්‍රියතම ... මෙම ප්‍රශ්නය දුටු විට මට ඇති වූ හැඟීම ප්‍රකාශ කිරීමට මට නොහැකිය.
ixtmixilix

2
@copy සෑම භාෂාවක් / සත්කාරක යුගලයක් සඳහාම ගොල්ෆ් තරඟයක් කිරීමට කිසි විටෙකත් ප්‍රමාද නැත
යවුහෙන් යකිමොවිච්

2
@ මාටින්බට්නර් ෂුවර්, ප්‍රශ්නය එම ටැගයට වඩා පැරණි වන අතර මූලික වශයෙන් එය කෙසේ හෝ ජනප්‍රිය තරගයක් වී ඇත
පිටපත

Answers:


84

දෙබලක හා ගොල්ෆ් කිරීමට නිදහස් වන්න: https://github.com/julienaubert/py8086

ප්‍රති ult ලය මම අන්තර්ක්‍රියාකාරී නිදොස් කිරීමක් ද ඇතුළත් කළෙමි.

CF:0 ZF:0 SF:0 IP:0x0000
AX:0x0000  CX:0x0000  DX:0x0000  BX:0x0000  SP:0x0100  BP:0x0000  SI:0x0000  DI:0x0000
AL:  0x00  CL:  0x00  DL:  0x00  BL:  0x00  AH:  0x00  CH:  0x00  DH:  0x00  BH:  0x00
stack: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ...
cmp SP, 0x100
[Enter]:step [R]:run [B 0xadr]:add break [M 0xadr]:see RAM [Q]:quit

B 0x10
M 0x1
M 0x1: 0xfc 0x00 0x01 0x74 0x01 0xf4 0xbc 0x00 0x10 0xb0 0x2e 0xbb ...
R

CF:0 ZF:0 SF:1 IP:0x0010
AX:0x002e  CX:0x0000  DX:0x0000  BX:0xffff  SP:0x1000  BP:0x0000  SI:0x0000  DI:0x0000
AL:  0x2e  CL:  0x00  DL:  0x00  BL:  0xff  AH:  0x00  CH:  0x00  DH:  0x00  BH:  0x00
stack: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ...
cmp BX, 0xffff
[Enter]:step [R]:run [B 0xadr]:add break [M 0xadr]:see RAM [Q]:quit

ලිපිගොනු තුනක් ඇත: emu8086.py (අත්‍යවශ්‍ය) console.py (දර්ශන ප්‍රතිදානය සඳහා විකල්ප), disasm.py (අත්‍යවශ්‍ය නොවේ, කේත ගොල්ෆ් හි asm ලැයිස්තුවක් ලබා ගැනීමට).

දර්ශනය සමඟ ධාවනය කිරීමට (සටහන ශාප භාවිතා කරයි):

python emu8086.py 

අන්තර්ක්‍රියාකාරී නිදොස්කරණය සමඟ ධාවනය කිරීමට:

python emu8086.py a b

අන්තර්ක්‍රියාකාරී නොවන "නිදොස්කරණය" සමඟ ධාවනය කිරීමට:

python emu8086.py a

" Codegolf " වැඩසටහන එකම නාමාවලියක තිබිය යුතුය.

emu8086.py

console.py

disasm.py

ගිතබ් මත


9
එය පළමු කෝඩ් ගොල්ෆ් කණුවක එක් අපායකි. +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 ...
ඩිලන් කවර්

@DC ස්තූතියි :) විනෝදජනක අභියෝගයක් විය!
ජා

1
කවුරුහරි ඇත්තටම මෙය කළ බව තවමත් විශ්වාස කළ නොහැක :-) නියම වැඩක්!
පිටපත් කරන්න

1
පුදුම! සුභ පැතුම්! අවසානයේ එය පේළි කීයක් තිබුණාද?
විල් එල්පී

59

හස්කල්, පේළි 256 234 196

මා කලක සිට මෙම වැඩ කටයුතු කරගෙන යමින් සිටියි, ප්‍රකාශයට පත් කිරීමට පෙර එය තව ටිකක් ඔප දැමීමට මම අදහස් කළෙමි, නමුත් දැන් විනෝදය නිල වශයෙන් ආරම්භ වී ඇත, එය තවදුරටත් සඟවා තබා ගැනීමට වැඩි යමක් නැත. එය නිස්සාරණය කරන විට එය හරියටම පේළි 256 ක් දිග බව මම දුටුවෙමි, එබැවින් එය එහි පැවැත්මේ “විශිෂ්ට” ස්ථානයක ඇතැයි සිතමි.

ඇති දේ: උදාහරණය ද්විමය දෝෂ රහිතව ක්‍රියාත්මක කිරීම සඳහා 8086 උපදෙස් කට්ටලයෙන් ප්‍රමාණවත් නොවේ. ස්වයං වෙනස් කිරීමේ කේතය සඳහා සහය දක්වයි. (prefetch: ශුන්‍ය බයිට්)
හාස්‍යයට කරුණක් නම්, කේතයේ පළමු ප්‍රමාණවත් පුනරාවර්තන දිගු වූ අතර ඔප්කෝඩ් පරතරයට වඩා අඩුවෙන් සහාය විය. ප්‍රතිනිර්මාණය කිරීම කේත දිගට සහ ඔප්කෝඩ් ආවරණයට ප්‍රයෝජනවත් විය.

අවසන් වී ඇති දේ: පැහැදිලිවම, කොටස්, උපසර්ග සහ බහු බයිට් ඔප්කෝඩ්, බාධා කිරීම්, අයි / ඕ වරාය, නූල් මෙහෙයුම් සහ එෆ්පී. මම මුලින් මුල් PUSH SPහැසිරීම අනුගමනය කළ නමුත් නැවත නැවත කිහිපයකින් පසුව එය අතහැර දැමීමට සිදුවිය.

රැගෙන යන ධජය ප්රතිඵල බොහෝ විට ඉතා ගත් අවස්ථා කිහිපයක් ගැන අවුල් වෙලා ඇත ADC/ SBB.

කෙසේ වෙතත්, මෙන්න කේතය:

------------------------------------------------------------
-- Imports

-- They're the only lines I allow to go over 80 characters.
-- For the simple reason the code would work just as well without the
-- actual symbol list, but I like to keep it up to date to better
-- grasp my dependency graph.

import           Control.Monad.Reader      (ReaderT,runReaderT,ask,lift,forever,forM,when,void)
import           Control.Monad.ST          (ST,runST)
import           Control.Monad.Trans.Maybe (MaybeT,runMaybeT)
import           Data.Array.ST             (STUArray,readArray,writeArray,newArray,newListArray)
import           Data.Bits                 (FiniteBits,(.&.),(.|.),xor,shiftL,shiftR,testBit,finiteBitSize)
import           Data.Bool                 (bool)
import qualified Data.ByteString as B      (unpack,getContents)
import           Data.Char                 (chr,isPrint) -- for screen dump
import           Data.Int                  (Int8)
import           Data.STRef                (STRef,newSTRef,readSTRef,writeSTRef,modifySTRef)
import           Data.Word                 (Word8,Word16)

------------------------------------------------------------
-- Bytes and Words
-- Bytes are 8 bits.  Words are 16 bits.  Addressing is little-endian.

-- Phantom types.  Essentially (only?) used for the ALU
byte = undefined :: Word8
word = undefined :: Word16

-- Byte to word conversion
byteToWordSE = (fromIntegral :: Int8 -> Word16) .
               (fromIntegral :: Word8 -> Int8)

-- Two-bytes to word conversion
concatBytes :: Word8 -> Word8 -> Word16
concatBytes l h = fromIntegral l .|. (fromIntegral h `shiftL` 8)

-- Word to two bytes conversion
wordToByteL,wordToByteH :: Word16 -> Word8
wordToByteL = fromIntegral
wordToByteH = fromIntegral . (`shiftR` 8)

-- A Place is an lvalue byte or word.  In absence of I/O ports, this
-- means RAM or register file.  This type synonym is not strictly
-- needed, but without it it's unclear I could keep the alu function
-- type signature under twice 80 characters, so why not keep this.
type Place s = (STUArray s Word16 Word8,Word16)

-- Read and write, byte or word, from RAM or register file

class (Ord a,FiniteBits a,Num a) => Width a where
  readW  :: Place s ->      MonadCPU s a
  writeW :: Place s -> a -> MonadCPU s ()

instance Width Word8 where
  readW  =  liftST    . uncurry readArray
  writeW = (liftST .) . uncurry writeArray

instance Width Word16 where
  readW (p,a) = concatBytes <$> readW (p,a) <*> readW (p,a+1)
  writeW (p,a) val = do
    writeW (p,a)   $ wordToByteL val
    writeW (p,a+1) $ wordToByteH val

------------------------------------------------------------
-- CPU object

-- The actual CPU state.  Yeah, I obviously don't have all flags in! :-D
data CPU s = CPU { ram  :: STUArray s Word16 Word8
                 , regs :: STUArray s Word16 Word8
                 , cf :: STRef s Bool
                 , zf :: STRef s Bool
                 , sf :: STRef s Bool }

newCPU rawRam = do ramRef <- newListArray (0,0xFFFF) rawRam
                   regFile <- newArray (0,17) 0
                   cf <- newSTRef False
                   zf <- newSTRef False
                   sf <- newSTRef False
                   return $ CPU ramRef regFile cf zf sf

-- Register addresses within the register file.  Note odd placement
-- for BX and related.  Also note the 16-bit registers have a wider
-- pitch.  IP was shoehorned in recently, it doesn't really need an
-- address here, but it made other code shorter, so that's that.

-- In the 8-bit subfile, only regAl is used in the code (and it's 0,
-- so consider that a line I could totally have skipped)
[regAl,regAh,regCl,regCh,regDl,regDh,regBl,regBh] = [0..7]

-- In the 16-bit file, they're almost if not all referenced.  8086
-- sure is clunky.
[regAx,regCx,regDx,regBx,regSp,regBp,regSi,regDi,regIp] = [0,2..16]

-- These functions look like I got part of the Lens intuition
-- independently, come to look at it after the fact.  Cool :-)
readCpu  ext   = liftST .      readSTRef    . ext =<< ask
writeCpu ext f = liftST . flip writeSTRef f . ext =<< ask

-- It looks like the only operations IP can receive are relative moves
-- (incrIP function below) and a single absolute set: RET.  I deduce
-- only short jumps, not even near, were in the spec.
incrIP i = do old <- readReg regIp
              writeReg regIp (old + i)
              return old

-- Read next instruction.  Directly from RAM, so no pipeline prefetch.
readInstr8 = incrIP 1 >>= readRam
readInstr16 = concatBytes <$> readInstr8 <*> readInstr8

-- RAM/register file R/W specializers
readReg  reg      = ask >>= \p -> readW  (regs p,reg)
readRam  addr     = ask >>= \p -> readW  (ram p ,addr)
writeReg reg val  = ask >>= \p -> writeW (regs p,reg)  val
writeRam addr val = ask >>= \p -> writeW (ram p ,addr) val

-- I'm not quite sure what those do anymore, or why they're separate.
decodeReg8  n = fromIntegral $ (n `shiftL` 1) .|. (n `shiftR` 2)
decodeReg16 n = fromIntegral $  n `shiftL` 1
readDecodedReg8 = readReg . decodeReg8
readDecodedReg16 = readReg . decodeReg16

-- The monad type synonym make type signatures easier :-(
type MonadCPU s = MaybeT (ReaderT (CPU s) (ST s))

-- Specialized liftST, because the one from Hackage loses the
-- parameter, and I need it to be able to qualify Place.
liftST :: ST s a -> MonadCPU s a
liftST = lift . lift

------------------------------------------------------------
-- Instructions

-- This is arguably the core secret of the 8086 architecture.
-- See statement links for actual explanations.
readModRM = do
  modRM <- readInstr8
  let mod   =  modRM           `shiftR` 6
      opReg = (modRM .&. 0x38) `shiftR` 3
      rm    =  modRM .&. 0x07
  cpu <- ask
  operand <- case mod of
               0 -> do
                 addr <- case rm of
                           1 -> (+) <$> readReg regBx <*> readReg regDi
                           2 -> (+) <$> readReg regBp <*> readReg regSi
                           6 -> readInstr16
                           7 -> readReg regBx
                 return (ram cpu,addr)
               2 -> do
                 addr <- case rm of
                           5 -> (+) <$> readReg regDi <*> readInstr16
                           7 -> (+) <$> readReg regBx <*> readInstr16
                 return (ram cpu,addr)
               3 -> return (regs cpu,2*fromIntegral rm)
  return (operand,opReg,opReg)

-- Stack operations.  PUSH by value (does NOT reproduce PUSH SP behavior)
push16 val = do
  sp <- subtract 2 <$> readReg regSp
  writeReg regSp sp
  writeRam sp (val :: Word16)
pop16 = do
  sp <- readReg regSp
  val <- readRam sp
  writeReg regSp (sp+2)
  return (val :: Word16)

-- So, yeah, JMP seems to be relative (short) only.  Well, if that's enough…
jump cond = when cond . void . incrIP . byteToWordSE =<< readInstr8

-- The ALU.  The most complicated type signature in this file.  An
-- initial argument as a phantom type I tried to get rid of and
-- failed.
alu :: Width w => w -> MonadCPU s w -> MonadCPU s w -> Place s
    -> (w -> w -> MonadCPU s (Bool,Maybe Bool,w)) -> MonadCPU s ()
alu _ a b r op = do
  (rw,c,v) <- a >>= (b >>=) . op
  when rw $ writeW r v
  maybe (return ()) (writeCpu cf) c
  writeCpu zf (v == 0)
  writeCpu sf (testBit v (finiteBitSize v - 1))
decodeALU 0 = \a b -> return (True, Just (a >= negate b),       a   +   b)
decodeALU 1 = \a b -> return (True, Just False,                 a  .|.  b)
decodeALU 2 = \a b -> bool 0 1 <$> readCpu cf >>= \c ->
                      return (True, Just (a >= negate (b + c)), a + b + c)
decodeALU 3 = \a b -> bool 0 1 <$> readCpu cf >>= \c ->
                      return (True, Just (a < b + c),           a - b - c)
decodeALU 4 = \a b -> return (True, Just False,                 a  .&.  b)
decodeALU 5 = \a b -> return (True, Just (a <= b),              a   -   b)
decodeALU 6 = \a b -> return (True, Just False,                 a `xor` b)
decodeALU 7 = \a b -> return (False,Just (a <= b),              a   -   b)
opIncDec :: Width w => w -> w -> MonadCPU s (Bool,Maybe Bool,w)
opIncDec    = \a b -> return (True, Nothing,                    a   +   b)

-- Main iteration: process one instuction
-- That's the rest of the meat, but that part's expected.
processInstr = do
  opcode <- readInstr8
  regs <- regs <$> ask
  let zReg = (regs,decodeReg16 (opcode .&. 0x07))
  if opcode < 0x40 then -- no segment or BCD
    let aluOp = (opcode .&. 0x38) `shiftR` 3 in case opcode .&. 0x07 of
    0 -> do
      (operand,reg,_) <- readModRM
      alu byte (readW operand) (readDecodedReg8 reg) operand (decodeALU aluOp)
    1 -> do
      (operand,reg,_) <- readModRM
      alu word (readW operand) (readDecodedReg16 reg) operand (decodeALU aluOp)
    4 -> alu byte (readReg regAl) readInstr8 (regs,regAl) (decodeALU aluOp)
  else case opcode .&. 0xF8 of -- 16-bit (mostly) reg ops
    0x40 -> alu word (readW zReg) (return   1 ) zReg opIncDec -- 16b INC
    0x48 -> alu word (readW zReg) (return (-1)) zReg opIncDec -- 16b DEC
    0x50 -> readW zReg >>= push16                       -- 16b PUSH reg
    0x58 -> pop16 >>= writeW zReg                       -- 16b POP reg
    0x90 -> do v1 <- readW zReg                         -- 16b XCHG (or NOP)
               v2 <- readReg regAx
               writeW zReg (v2 :: Word16)
               writeReg regAx (v1 :: Word16)
    0xB0 -> readInstr8  >>= writeW zReg -- (BUG!)       -- 8b MOV reg,imm
    0xB8 -> readInstr16 >>= writeW zReg                 -- 16b MOV reg,imm
    _ -> case bool opcode 0x82 (opcode == 0x80) of
      0x72 -> jump       =<< readCpu cf                 -- JB/JNAE/JC
      0x74 -> jump       =<< readCpu zf                 -- JE/JZ
      0x75 -> jump . not =<< readCpu zf                 -- JNE/JNZ
      0x76 -> jump       =<< (||) <$> readCpu cf <*> readCpu zf -- JBE
      0x77 -> jump . not =<< (||) <$> readCpu cf <*> readCpu zf -- JA
      0x79 -> jump . not =<< readCpu sf                 -- JNS
      0x81 -> do                                        -- 16b arith to imm
        (operand,_,op) <- readModRM
        alu word (readW operand) readInstr16 operand (decodeALU op)
      0x82 -> do                                        -- 8b arith to imm
        (operand,_,op) <- readModRM
        alu byte (readW operand) readInstr8 operand (decodeALU op)
      0x83 -> do                                        -- 16b arith to 8s imm
        (operand,_,op) <- readModRM
        alu word (readW operand) (byteToWordSE <$> readInstr8) operand
            (decodeALU op)
      0x86 -> do                                        -- 8b XCHG reg,RM
        (operand,reg,_) <- readModRM
        v1 <- readDecodedReg8 reg
        v2 <- readW operand
        writeReg (decodeReg8 reg) (v2 :: Word8)
        writeW operand v1
      0x88 -> do                                        -- 8b MOV RM,reg
        (operand,reg,_) <- readModRM
        readDecodedReg8 reg >>= writeW operand
      0x89 -> do                                        -- 16b MOV RM,reg
        (operand,reg,_) <- readModRM
        readDecodedReg16 reg >>= writeW operand
      0x8A -> do                                        -- 8b MOV reg,RM
        (operand,reg,_) <- readModRM
        val <- readW operand
        writeReg (decodeReg8 reg) (val :: Word8)
      0x8B -> do                                        -- 16b MOV reg,RM
        (operand,reg,_) <- readModRM
        val <- readW operand
        writeReg (decodeReg16 reg) (val :: Word16)
      0xC3 -> pop16 >>= writeReg regIp                  -- RET
      0xC7 -> do (operand,_,_) <- readModRM             -- 16b MOV RM,imm
                 readInstr16 >>= writeW operand
      0xE8 -> readInstr16 >>= incrIP >>= push16         -- CALL relative
      0xEB -> jump True                                 -- JMP short
      0xF4 -> fail "Halting and Catching Fire"          -- HLT
      0xF9 -> writeCpu cf True                          -- STC
      0xFE -> do                                        -- 8-bit INC/DEC RM
        (operand,_,op) <- readModRM
        alu byte (readW operand) (return $ 1-2*op) operand
            (\a b -> return (True,Nothing,a+b)) -- kinda duplicate :(

------------------------------------------------------------

main = do
  rawRam <- (++ repeat 0) . B.unpack <$> B.getContents
  putStr $ unlines $ runST $ do
    cpu <- newCPU rawRam
    flip runReaderT cpu $ runMaybeT $ do
      writeReg regSp (0x100 :: Word16)
      forever processInstr

    -- Next three lines is the screen dump extraction.
    forM [0..25] $ \i -> forM [0..79] $ \j -> do
      c <- chr . fromIntegral <$> readArray (ram cpu) (0x8000 + 80*i + j)
      return $ bool ' ' c (isPrint c)

සපයන ලද නියැදි ද්විමය සඳහා ප්‍රතිදානය පිරිවිතරයට හොඳින් ගැලපේ. ආයාචනයක් භාවිතා කර එය අත්හදා බලන්න:

runhaskell 8086.hs <8086.bin

ක්‍රියාත්මක නොකරන ලද බොහෝ මෙහෙයුම් සරලවම රටා ගැලපීම අසාර්ථක වීමට හේතු වේ.

මම තව ටිකක් වැඩි සාධකයක් කිරීමට අදහස් කරමි, සහ ශාපයන් සමඟ සැබෑ සජීවී ප්‍රතිදානය ක්‍රියාත්මක කරන්න.

යාවත්කාලීන 1: එය පේළි 234 දක්වා පහත බැස ඇත. ක්‍රියාකාරීත්වය අනුව කේතය වඩා හොඳින් සංවිධානය කිරීම, විය හැකි දේ නැවත පෙළගැස්වීම, තීරු 80 කට ඇලී සිටීමට උත්සාහ කිරීම. තවද ALU කිහිප වතාවක් ප්‍රතිනිර්මාණය කරන ලදි.

යාවත්කාලීනය 2: එය වසර පහක් ගතවී ඇත, නවතම GHC හි අනුපිළිවෙලින් විය හැකි දෝෂ රහිතව සම්පාදනය කිරීම සඳහා යාවත්කාලීන කිරීමක් මම සොයා ගතිමි. මඟ දිගේ:

  • ලිෆ්ට් එම්, ලිෆ්ට් එම් 2 සහ එවැනි දේ ඉවත් කර ඇත. මම ටිකත් <$>හා <*>පූර්විකාවක් විය.
  • Data.Bool සහ Data.ByteString, ටිකක් ඉතිරි කර පිරිසිදු කරයි.
  • IP ලේඛනය විශේෂ (විස්තර කළ නොහැකි) විය, දැන් එය රෙජිස්ටර් ගොනුවේ ඇත. එය එතරම් 8086 තේරුමක් නැත, නමුත් හේයි මම ගොල්ෆ් ක්‍රීඩකයෙක්.
  • ඒ සියල්ල දැන් පිරිසිදු ST මත පදනම් වූ කේතයයි. ගොල්ෆ් ක්‍රීඩා දෘෂ්ටි කෝණයකින්, මෙය උරා බොන්නේ, එය බොහෝ වර්ගවල අත්සන් අවශ්‍ය වූ බැවිනි. අනෙක් අතට, මගේ හෘදය සාක්ෂිය සමඟ පේළියක් තිබූ අතර මට අහිමි විය, එබැවින් දැන් ඔබට පිරිසිදු දිගු කේතය ලැබේ.
  • ඉතින් දැන් මෙය git-track.
  • වඩාත් බැරෑරුම් අදහස් එකතු කරන ලදි. එහි ප්‍රති consequ ලයක් ලෙස, මම රේඛා ගණන් කරන ආකාරය වෙනස් වී ඇත: මම හිස් හා පිරිසිදු අදහස් දැක්වීම් රේඛා අතහරින්නෙමි. මම මෙයින් සියලු රේඛා සහතික කරමි නමුත් ආනයන අක්ෂර 80 ට වඩා අඩුය. මා විසින් අත්සන අතහැර දමන්නේ නැත, මන්ද එය නිසියාකාරව සම්පාදනය කිරීම සඳහා මා විසින් ඉතිරි කර ඇති දෙය අවශ්‍ය වන හෙයිනි (ස්තුතියි ST පිරිසිදුකම).

කේත විවරණ වල දැක්වෙන පරිදි, පේළි 5 ක් (Data.Char ආනයනය, 8-බිට් රෙජිස්ටර් සිතියම්කරණය සහ තිර ඩම්ප්) පිරිවිතරයෙන් බැහැරව ඇත, එබැවින් ඔබට එතරම් නැඹුරුවක් දැනේ නම් ඒවා වට්ටම් කිරීමට ඔබව සාදරයෙන් පිළිගනිමු :-)


3
කදිම එකක්. එය ඇත්තෙන්ම කෙටි ය, විශේෂයෙන් මගේ විසඳුම හා අනෙක් විසඳුම සමඟ සසඳන විට. මට මුලින් හැස්කෙල් ඉගෙන ගත යුතු වුවත් ඔබේ කේතය ඉතා හොඳ පෙනුමක් ඇත.
පිටපත් කරන්න

3
නියම වැඩක්! ඉතා කෙටි ය. මම හැස්කල් ඉගෙන ගත යුතුයි.
ජා

මොකක්ද .|.? / 10 චාර්
චෞද්රි

x86 ඔප්කෝඩ් වල OR ලෙස හැඳින්වෙන මෙහෙයුම.
ජේ බී

46

සී - 7143 පේළි (CPU විසින්ම පේළි 3162)

සංස්කරණය කරන්න: වින්ඩෝස් බිල්ඩ් හි දැන් අතථ්‍ය තැටි වෙනස් කිරීම සඳහා පතන මෙනු ඇත.

මම සම්පූර්ණ 80186 / V20 PC emulator එකක් (CGA / MCGA / VGA, සවුන්ඩ් බ්ලාස්ටර්, ඇඩ්ලිබ්, මූසිකය ආදිය සමඟ) ලියා ඇත, 8086 ඕනෑම ආකාරයකින් අනුකරණය කිරීම සුළුපටු දෙයක් නොවේ. සම්පූර්ණයෙන්ම නිවැරදි වීමට මාස ගණනාවක් ගත විය. මෙන්න CPU මොඩියුලය මගේ ඉමියුලේටරයෙන් පමණි.

http://sourceforge.net/p/fake86/code/ci/master/tree/src/fake86/cpu.c

මෙම ඉමියුලේටරය තුළ මම බොහෝ ගෝලීය විචල්‍යයන් භාවිතා කරන බව පිළිගැනීමට පළමුවැන්නා වෙමි. මම මෙය ලිවීමට පටන් ගත්තේ මම සී ට තවමත් අලුත් වූ විටය. මට මේ දිනවල එකක් පිරිසිදු කිරීමට අවශ්‍යයි. එහි ඇති අනෙකුත් බොහෝ මූලාශ්‍ර ලිපිගොනු එතරම් කැත ලෙස නොපෙනේ.

ඔබට මෙහි සියලුම කේත (සහ සමහර තිරපිටපත් එකක් පහතින්) දැක ගත හැකිය: http://sourceforge.net/p/fake86

තමන්ගේම ලිවීමට කැමති වෙනත් ඕනෑම කෙනෙකුට උදව් කිරීමට මම ඉතා සතුටු වෙමි, මන්ද එය බොහෝ විනෝදජනක වන අතර ඔබ CPU ගැන බොහෝ දේ ඉගෙන ගනී! වියාචනය: V20 හි 8080 අනුකරණයන් කිසි විටෙකත් පරිගණක වැඩසටහනක භාවිතා කර නොමැති බැවින් මම එය එකතු නොකළෙමි. කිසිදු වාසියක් නොමැතිව විශාල වැඩ කොටසක් සේ පෙනේ.

ස්ට්‍රීට් ෆයිටර් 2!


3
හොඳ වැඩක්! ක්‍රීඩා සැබවින්ම සම්පූර්ණ වේගයෙන් ධාවනය වේද?
පිටපත

1
ස්තූතියි. ඔව්, එය 8088 ට වඩා බොහෝ ගුණයකින් වේගයෙන් ධාවනය වේ. නවීන පද්ධතියක එයට 486 වැනි වේගයක් කළ හැකිය. නියම හොඳ සකසනයක, එය පහත් මට්ටමේ පෙන්ටියම් වැනි ය. අවාසනාවකට මෙන් CPU එකක් අනුකරණය කිරීම ඇත්ත වශයෙන්ම බහු-ත්‍රෙඩ් කළ නොහැක. මම සියළුම වීඩියෝ විදැහුම්කරණය කරන්නේ එයමයි. මම එය මගේ පැරණි 400 MHz PowePC G3 මත ධාවනය කර ඇත්තෙමි, එය සත්‍ය වේග 8088 දක්වා පහත බැස ඇත.
මයික් සී

1
නියමයි! තවත් දෘෂ්ටි කේත සහ ඛණ්ඩනය ක්‍රියාත්මක කිරීමට මට අවශ්‍ය විය; කෙසේ වෙතත්, එය ක්‍රියාත්මක කිරීම සඳහා බොහෝ පරීක්ෂණ වැඩසටහන් සොයා ගැනීමට නොහැකි විය. ඔබ පැරණි roms බාගත කළාද?
ඩේව් සී

1
ඩේව්, ඇත්ත වශයෙන්ම ඔබ ද සොයාගත් පරිදි පුදුම සහගත ලෙස ටෙස්ට් රෝම් 8086 හි බරපතල lack නතාවක් නොමැත. මා ඒ සඳහා ගිය මාර්ගය වූයේ සාමාන්‍ය XT BIOS ROM එකක් නිවැරදිව ධාවනය කිරීමෙන් ආරම්භ කිරීමයි. එතරම් වැඩ කරන්නේ නම්, ඔබේ ඛණ්ඩනය හොඳයි. ඊට පසු, ඩොස් වැඩ කිරීමට පටන් ගන්නා තෙක් එය නිදොස්කරණය කිරීමක් විය ... ඉන්පසු යෙදුම් සහ ක්‍රීඩා වෙත! :)
මයික් සී

1
IkeMikeC මම ආරම්භක උදව් හෝ කරුණු කිහිපයක් කැමතියි! (පුන් අදහස්: පී). මම දැන් වසර ගණනාවක් තිස්සේ ඩෙස්ක්ටොප් සහ වෙබ් යෙදුම් සංවර්ධකයෙකු වන අතර සෙමින් මම ලිනක්ස් ප්‍රභව කේතය ඇති තැනකට පැමිණ සිටිමි. මෙහෙයුම් පද්ධතියක විවිධ කොටස් ක්‍රියා කරන ආකාරය සහ කුඩා සෙල්ලම් බඩු මෙහෙයුම් පද්ධති ව්‍යාපෘති සමඟ සෙල්ලම් කිරීමට මට හැකි වූයේ කෙසේදැයි මම සාමාන්‍යයෙන් තේරුම් ගතිමි. නමුත් සෘජු දෘඩාංග සමඟ අන්තර් ක්‍රියා කිරීමෙන් මා වැළකී සිටියි!
ගිඩියොන්

41

තැපැල් පිටපත (130 යි 200 යි 367 517 531 යි 222 පේළි 246)

තවමත් ක්‍රියාත්මක වෙමින් පවතී, නමුත්මට අවශ්‍ය වූයේ යම් කේතයක් පෙන්වීමට අන් අයව දිරිමත් කිරීම සඳහා යම් කේතයක් පෙන්වීමටය .

රෙජිස්ටර් කට්ටලය එක් නූලක් ලෙස නිරූපණය කර ඇති බැවින් විවිධ බයිට් හා වචන ප්‍රමාණයේ රෙජිස්ටරයන් උපස්ථර වෙත යොමු කිරීමෙන් ස්වභාවිකව අතිච්ඡාදනය විය හැකිය. උපස්ථරයන් පුරාම දර්ශකයන් ලෙස භාවිතා කරනු ලැබේ, එවිට ලේඛක සහ මතක ස්ථානයක් (මතක නූලට උපස්ථරයක්) ක්‍රියාකරුගේ ක්‍රියාකාරකම් වලදී ඒකාකාරව සැලකිය හැකිය.

"දර්ශකය" වෙතින්, මතකයෙන්, මතකයෙන් (IP)] (IP වැඩි කිරීම) වෙතින් දත්ත (බයිට් හෝ වචනය) ලබා ගැනීමට සහ ගබඩා කිරීමට වචන අතලොස්සක් ඇත. එවිට MOD-REG-R / M බයිට් ලබා ගැනීමට සහ REG සහ R / M සහ MOD විචල්‍යයන් සැකසීමට සහ වගු භාවිතයෙන් විකේතනය කිරීමට කාර්යයන් කිහිපයක් තිබේ. එවිට ක්‍රියාකරු ක්‍රියා කරයි, ඔප්කෝඩ් බයිටයට යතුර. එබැවින් ක්‍රියාත්මක කිරීමේ ලූපය සරලවම fetchb load execවේ.

මා සතුව ඇත්තේ ඔප්කෝඩ් අතළොස්සක් පමණි, නමුත් උඔපෙරන්ඩ් විකේතනය ලබා ගැනීම එවැනි සන්ධිස්ථානයක් සේ මට එය බෙදා ගැනීමට අවශ්‍ය විය.

සංස්කරණය කරන්න: negative ණ සංඛ්‍යා අත්සන් කිරීමට වචන එකතු කරන ලදි. තවත් ඔප්කෝඩ්. ලේඛණ පැවරුම්වල දෝෂ නිරාකරණය. අදහස්. තවමත් ධජ මත වැඩ කරමින් ක්‍රියාකරුවන් පිරවීම. ප්‍රතිදානය මඟින් සමහර තේරීම් ඉදිරිපත් කරයි: නිමැවුම් පා st ය අවසන් කිරීම සඳහා ස්ථාවර කිරීම, vt100 කේත භාවිතා කරමින් අඛණ්ඩව ප්‍රතිදානය කිරීම, CP437 අකුරු භාවිතා කරමින් රූප කවුළුව වෙත ප්‍රතිදානය.

සංස්කරණය: ලිවීම අවසන්, නිදොස්කරණය ආරම්භ කිරීම. එය නිමැවුම් පළමු තිත් හතර ලබා ගනී! එවිට රැගෙන යාම වැරදී යයි. නිදිමත.

සංස්කරණය කරන්න: මම හිතන්නේ මම කැරි කොඩිය වර්ග කර ඇත. සමහර කතාව comp.lang.postscript හි සිදු විය . මම නිදොස් කිරීමේ උපකරණ කිහිපයක් එකතු කර ඇති අතර, ප්‍රතිදානය ග්‍රැෆික් කවුළුව වෙත යයි (මා කලින් ලියා ඇති කේත-පිටුව 437 වර්ගය -3 අකුරු භාවිතා කරමින් ), එබැවින් පෙළ ප්‍රතිදානය අංශු මාත්‍ර හා ඩම්ප් වලින් පිරී තිබිය හැකිය. එහි "හෙලෝ වර්ල්ඩ්!" ඊට පස්සෙ ඒ සැක සහිත කරත්තය තියෙනවා. එහෙනම් මුළු ලොටා නෝටින් '. :( අපි එහි යමු. සියලු දිරිගැන්වීම් වලට ස්තූතියි!

සංස්කරණය: පරීක්ෂණය සම්පූර්ණ කිරීම දක්වා ධාවනය කරයි. අවසාන දෝෂ කිහිපය නම්: XCHG 2 {කියවීමේ ගබඩාවක්} හුවමාරුවට වඩා පිටපත් කවරේද යන්න පුනරාවර්තනය කරන්න, සහ කොඩි සැකසීම නොවේ, (FE) INC බයිට් පොයින්ටරයකින් වචනයක් ලබා ගැනීමට උත්සාහ කරයි.

සංස්කරණය කරන්න: අත්පොතේ සංක්ෂිප්ත වගුව භාවිතා කරමින් මුල සිටම නැවත ලිවීම ( නව පිටුවක් හැරවීම! ). මම හිතන්න පටන් ගන්නවා ඔප්කෝඩ් වලින් සාප්පුව පිට කිරීම නරක අදහසක් කියලා, නමුත් එය ඔප්ටාබ් එක ලස්සනට තියාගන්න උදව් වුණා. මෙවර තිර රුවක් නැත. වීඩියෝ මතකය ඉවත ලෑම සඳහා මම උපදෙස් කවුන්ටරයක් ​​සහ මෝඩ්-ප්‍රේරකයක් එක් කළෙමි, එබැවින් එය නිදොස් කිරීමේ තොරතුරු සමඟ පහසුවෙන් සම්බන්ධ වේ.

සංස්කරණය කරන්න: නැවත පරීක්ෂණ වැඩසටහන ක්‍රියාත්මක කරයි! කෙටි නැවත ලිවීම සඳහා වූ අවසාන දෝෂ කිහිපය වූයේ ඔප්කෝඩ් 83 ("ක්ෂණික" කණ්ඩායම) සහ ඊබී (කෙටි ජේඑම්පී) හි ක්ෂණික බයිටය අත්සන් කිරීමට නොසලකා හැරීමයි. පේළි 24 කින් වැඩි කිරීම මඟින් එම අවසාන දෝෂ සොයා ගැනීමට අවශ්‍ය අතිරේක නිදොස්කරණය කිරීමේ ක්‍රම ආවරණය කරයි.

%!
%a8086.ps Draught2:BREVITY
[/NULL<0000>/nul 0
/mem 16#ffff string %16-bit memory
/CF 0 /OF 0 /AF 0 /ZF 0 /SF 0
/regs 20 string >>begin %register byte storage
0{AL AH CL CH DL DH BL BH}{regs 2 index 1 getinterval def 1 add}forall pop
0{AX CX DX BX SP BP SI DI IP FL}{regs 2 index 2 getinterval def 2 add}forall pop

%getting and fetching
[/*b{0 get} %get byte from pointer
/*w{dup *b exch 1 get bbw} %get word from pointer
/*{{*b *w}W get exec} %get data(W) from pointer
/bbw{8 bitshift add} %lo-byte hi-byte -> word
/shiftmask{2 copy neg bitshift 3 1 roll 1 exch bitshift 1 sub and}
/fetchb{IP *w mem exch get bytedump   IP dup *w 1 add storew} % byte(IP++)
/fetchw{fetchb fetchb bbw} % word(IP),IP+=2

%storing and accessing
/storeb{16#ff and 0 exch put} % ptr val8 -> -
/storew{2 copy storeb -8 bitshift 16#ff and 1 exch put} % ptr val16 -> -
/stor{{storeb storew}W get exec} % ptr val(W) -> -
/memptr{16#ffff and mem exch {1 2}W get getinterval} % addr -> ptr(W)

%decoding the mod-reg-reg/mem byte
/mrm{fetchb 3 shiftmask /RM exch def 3 shiftmask /REG exch def /MOD exch def}
/REGTAB[[AL CL DL BL AH CH DH BH][AX CX DX BX SP BP SI DI]]
/decreg{REGTAB W get REG get} % REGTAB[W][REG]
%2 indexes,   with immed byte,   with immed word
/2*w{exch *w exch *w add}/fba{fetchb add}/fwa{fetchw add}
/RMTAB[[{BX SI 2*w}{BX DI 2*w}{BP SI 2*w}{BP DI 2*w}
    {SI *w}{DI *w}{fetchw}{BX *w}]
[{BX SI 2*w fba}{BX DI 2*w fba}{BP SI 2*w fba}{BP DI 2*w fba}
    {SI *w fba}{DI *w fba}{BP *w fba}{BX *w fba}]
[{BX SI 2*w fwa}{BX DI 2*w fwa}{BP SI 2*w fwa}{BP DI 2*w fwa}
    {SI *w fwa}{DI *w fwa}{BP *w fwa}{BX *w fwa}]]
/decrm{MOD 3 eq{REGTAB W get RM get} %MOD=3:register mode
    {RMTAB MOD get RM get exec memptr}ifelse} % RMTAB[MOD][RM] -> addr -> ptr

%setting and storing flags
/flagw{OF 11 bitshift SF 7 bitshift or ZF 6 bitshift or AF 4 bitshift CF or}
/wflag{dup 1 and /CF exch def dup -4 bitshift 1 and /AF exch def
    dup -6 bitshift 1 and /ZF exch def dup -7 bitshift 1 and /SF exch def
    dup -11 bitshift 1 and /OF exch def}
/nz1{0 ne{1}{0}ifelse}
/logflags{/CF 0 def /OF 0 def /AF 0 def %clear mathflags
    dup {16#80 16#8000}W get and nz1 /SF exch def
    dup {16#ff 16#ffff}W get and 0 eq{1}{0}ifelse /ZF exch def}
/mathflags{{z y x}{exch def}forall
    /CF z {16#ff00 16#ffff0000}W get and nz1 def
    /OF z x xor z y xor and {16#80 16#8000}W get and nz1 def
    /AF x y xor z xor 16#10 and nz1 def
    z} %leave the result on stack

%opcodes (each followed by 'stor')  %% { OPTAB fetchb get exec stor } loop
/ADD{2 copy add logflags mathflags}
/OR{or logflags}
/ADC{CF add ADD}
/SBB{D 1 xor {exch}repeat CF add 2 copy sub logflags mathflags}
/AND{and logflags}
/SUB{D 1 xor {exch}repeat 2 copy sub logflags mathflags}
/XOR{xor logflags}
/CMP{3 2 roll pop NULL 3 1 roll SUB} %dummy stor target
/INC{t CF exch dup * 1 ADD 3 2 roll /CF exch def}
/DEC{t CF exch dup * 1 SUB 3 2 roll /CF exch def}
/PUSH{SP dup *w 2 sub storew   *w SP *w memptr exch}
/POP{SP *w memptr *w   SP dup *w 2 add storew}

/jrel{w {CBW IP *w add IP exch}{NULL exch}ifelse}
/JO{fetchb OF 1 eq jrel }
/JNO{fetchb OF 0 eq jrel }
/JB{fetchb CF 1 eq jrel }
/JNB{fetchb CF 0 eq jrel }
/JZ{fetchb ZF 1 eq jrel }
/JNZ{fetchb ZF 0 eq jrel }
/JBE{fetchb CF ZF or 1 eq jrel }
/JNBE{fetchb CF ZF or 0 eq jrel }
/JS{fetchb SF 1 eq jrel }
/JNS{fetchb SF 0 eq jrel }
/JL{fetchb SF OF xor 1 eq jrel }
/JNL{fetchb SF OF xor 0 eq jrel }
/JLE{fetchb SF OF xor ZF or 1 eq jrel }
/JNLE{fetchb SF OF xor ZF or 0 eq jrel }

/bw{dup 16#80 and 0 ne{16#ff xor 1 add 16#ffff xor 1 add}if}
/IMMTAB{ADD OR ADC SBB AND SUB XOR CMP }cvlit
/immed{ W 2 eq{ /W 1 def
            mrm decrm dup * fetchb bw
    }{ mrm decrm dup * {fetchb fetchw}W get exec }ifelse
    exch IMMTAB REG get dup == exec }

%/TEST{ }
/XCHG{3 2 roll pop 2 copy exch * 4 2 roll * stor }
/AXCH{w dup AX XCHG }
/NOP{ NULL nul }
/pMOV{D{exch}repeat pop }
/mMOV{ 3 1 roll pop pop }
/MOV{ }
/LEA{w mrm decreg RMTAB MOD get RM get exec }

/CBW{dup 16#80 and 0 ne {16#ff xor 1 add 16#ffff xor 1 add } if }
/CWD{dup 16#8000 and 0 ne {16#ffff xor 1 add neg } if }
/CALL{w xp /xp{}def fetchw IP PUSH storew IP dup *w 3 2 roll add dsp /dsp{}def }
%/WAIT{ }
/PUSHF{NULL dup flagw storew 2 copy PUSH }
/POPF{NULL dup POP *w wflag }
%/SAHF{ }
%/LAHF{ }

%/MOVS{ }
%/CMPS{ }
%/STOS{ }
%/LODS{ }
%/SCAS{ }
/RET{w IP POP storew SP dup * 3 2 roll add }
%/LES{ }
%/LDS{ }

/JMP{IP dup fetchw exch *w add}
/sJMP{IP dup fetchb bw exch *w add}

/HLT{exit}
/CMC{/CF CF 1 xor def NULL nul}
/CLC{/CF 0 def NULL nul}
/STC{/CF 1 def NULL nul}

/NOT{not logflags }
/NEG{neg logflags }
/GRP1TAB{TEST --- NOT NEG MUL IMUL DIV IDIV } cvlit
/Grp1{mrm decrm dup * GRP1TAB REG get
dup ==
exec }
/GRP2TAB{INC DEC {id CALL}{l id CALL}{id JMP}{l id JMP} PUSH --- } cvlit
/Grp2{mrm decrm GRP2TAB REG get
dup ==
exec }

%optab shortcuts
/2*{exch * exch *}
/rm{mrm decreg decrm D index 3 1 roll 2*} % fetch,decode mrm -> dest *reg *r-m
/rmp{mrm decreg decrm D index 3 1 roll} % fetch,decode mrm -> dest reg r-m
/ia{ {{AL dup *b fetchb}{AX dup *w fetchw}}W get exec } %immed to accumulator
/is{/W 2 def}
/b{/W 0 def} %select byte operation
/w{/W 1 def} %select word operation
/t{/D 1 def} %dest = reg
/f{/D 0 def} %dest = r/m
/xp{} /dsp{}
%/far{ /xp { <0000> PUSH storew } /dsp { fetchw pop } def }
/i{ {fetchb fetchw}W get exec }

/OPTAB{
{b f rm ADD}{w f rm ADD}{b t rm ADD}{w t rm ADD}{b ia ADD}{w ia ADD}{ES PUSH}{ES POP} %00-07
 {b f rm OR}{w f rm OR}{b t rm OR}{w t rm OR}{b ia OR}{w ia OR}{CS PUSH}{}            %08-0F
{b f rm ADC}{w f rm ADC}{b t rm ADC}{w t rm ADC}{b ia ADC}{w ia ADC}{SS PUSH}{SS POP} %10-17
 {b f rm SBB}{w f rm SBB}{b t rm SBB}{w t rm SBB}{b ia SBB}{w ia SBB}{DS PUSH}{DS POP}%18-1F
{b f rm AND}{w f rm AND}{b t rm AND}{w t rm AND}{b ia AND}{w ia AND}{ES SEG}{DAA}     %20-27
 {b f rm SUB}{w f rm SUB}{b t rm SUB}{w t rm SUB}{b ia SUB}{w ia SUB}{CS SEG}{DAS}    %28-2F
{b f rm XOR}{w f rm XOR}{b t rm XOR}{w t rm XOR}{b ia XOR}{w ia XOR}{SS SEG}{AAA}     %30-37
 {b f rm CMP}{w f rm CMP}{b t rm CMP}{w t rm CMP}{b ia CMP}{w ia CMP}{DS SEG}{AAS}    %38-3F
{w AX INC}{w CX INC}{w DX INC}{w BX INC}{w SP INC}{w BP INC}{w SI INC}{w DI INC}      %40-47
 {w AX DEC}{w CX DEC}{w DX DEC}{w BX DEC}{w SP DEC}{w BP DEC}{w SI DEC}{w DI DEC}     %48-4F
{AX PUSH}{CX PUSH}{DX PUSH}{BX PUSH}{SP PUSH}{BP PUSH}{SI PUSH}{DI PUSH}              %50-57
 {AX POP}{CX POP}{DX POP}{BX POP}{SP POP}{BP POP}{SI POP}{DI POP}                     %58-5F
{}{}{}{}{}{}{}{}  {}{}{}{}{}{}{}{}                                                    %60-6F
{JO}{JNO}{JB}{JNB}{JZ}{JNZ}{JBE}{JNBE} {JS}{JNS}{JP}{JNP}{JL}{JNL}{JLE}{JNLE}         %70-7F

{b f immed}{w f immed}{b f immed}{is f immed}{b TEST}{w TEST}{b rmp XCHG}{w rmp XCHG}   %80-87
 {b f rm pMOV}{w f rm pMOV}{b t rm pMOV}{w t rm pMOV}                                 %88-8B
   {sr f rm pMOV}{LEA}{sr t rm pMOV}{w mrm decrm POP}                                 %8C-8F
{NOP}{CX AXCH}{DX AXCH}{BX AXCHG}{SP AXCH}{BP AXCH}{SI AXCH}{DI AXCH}             %90-97
 {CBW}{CWD}{far CALL}{WAIT}{PUSHF}{POPF}{SAHF}{LAHF}                                  %98-9F
{b AL m MOV}{w AX m MOV}{b m AL MOV}{b AX m MOV}{MOVS}{MOVS}{CMPS}{CMPS}              %A0-A7
 {b i a TEST}{w i a TEST}{STOS}{STOS}{LODS}{LODS}{SCAS}{SCAS}                         %A8-AF
{b AL i MOV}{b CL i MOV}{b DL i MOV}{b BL i MOV}                                      %B0-B3
 {b AH i MOV}{b CH i MOV}{b DH i MOV}{b BH i MOV}                                     %B4-B7
 {w AX i MOV}{w CX i MOV}{w DX i MOV}{w BX i MOV}                                     %B8-BB
 {w SP i MOV}{w BP i MOV}{w SI i MOV}{w DI i MOV}                                     %BC-BF
{}{}{fetchw RET}{0 RET}{LES}{LDS}{b f rm i mMOV}{w f rm i mMOV}                       %C0-B7
 {}{}{fetchw RET}{0 RET}{3 INT}{fetchb INT}{INTO}{IRET}                               %C8-CF
{b Shift}{w Shift}{b v Shift}{w v Shift}{AAM}{AAD}{}{XLAT}                            %D0-D7
 {0 ESC}{1 ESC}{2 ESC}{3 ESC}{4 ESC}{5 ESC}{6 ESC}{7 ESC}                             %D8-DF
{LOOPNZ}{LOOPZ}{LOOP}{JCXZ}{b IN}{w IN}{b OUT}{w OUT}                                 %E0-E7
 {CALL}{JMP}{far JMP}{sJMP}{v b IN}{v w IN}{v b OUT}{v w OUT}                         %E8-EF
{LOCK}{}{REP}{z REP}{HLT}{CMC}{b Grp1}{w Grp}                                         %F0-F7
 {CLC}{STC}{CLI}{STI}{CLD}{STD}{b Grp2}{w Grp2}                                       %F8-FF
}cvlit

/break{ /hook /pause load def }
/c{ /hook {} def }
/doprompt{
    (\nbreak>)print
    flush(%lineedit)(r)file
    cvx {exec}stopped pop }
/pause{ doprompt }
/hook{}

/stdout(%stdout)(w)file
/bytedump{ <00> dup 0 3 index put stdout exch writehexstring ( )print }
/regdump{ REGTAB 1 get{ stdout exch writehexstring ( )print }forall
    stdout IP writehexstring ( )print
    {(NC )(CA )}CF get print
    {(NO )(OV )}OF get print
    {(NS )(SN )}SF get print
    {(NZ )(ZR )}ZF get print
    stdout 16#1d3 w memptr writehexstring
    (\n)print
}
/mainloop{{
    %regdump
    OPTAB fetchb get
    dup ==
    exec
    %pstack flush
    %hook
    stor
    /ic ic 1 add def ictime
}loop}

/printvideo{
    0 1 28 {
        80 mul 16#8000 add mem exch 80 getinterval {
            dup 0 eq { pop 32 } if
                    dup 32 lt 1 index 126 gt or { pop 46 } if
            stdout exch write
        } forall (\n)print
    } for
    (\n)print
}
/ic 0
/ictime{ic 10 mod 0 eq {onq} if}
/timeq 10
/onq{ %printvideo
}
>>begin
currentdict{dup type/arraytype eq 1 index xcheck and
    {bind def}{pop pop}ifelse}forall

SP 16#100 storew
(codegolf.8086)(r)file mem readstring pop
pop[

mainloop
printvideo

%eof

සහ ප්‍රතිදානය (සංක්ෂිප්ත නිදොස් කිරීමේ ප්‍රතිදානයේ වලිගය සමඟ).

75 {JNZ}
19 43 {w BX INC}
83 {is f immed}
fb 64 CMP
76 {JBE}
da f4 {HLT}
.........
Hello, world!
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~


################################################################################
##                                                                            ##
##  0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987                          ##
##                                                                            ##
##  0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400     ##
##                                                                            ##
##  2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97    ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
################################################################################





GS<1>

5
මට පුදුමයි ... F4h 8086 HLT opcode නිසා alt-F4 යෙදුමක් වැසීමට උණුසුම් යතුරක් තිබේද?
luser droog

6
තැපැල් පිටපතෙහි මෙය ක්‍රියාත්මක කිරීම සඳහා ඔබ නියමයි කියා මට කියන්නට අවශ්‍යයි.
cemper93

1
එම කේතය කෙටි ය . එය වැඩි දියුණුවක් ලැබීමට සුදුසුයි. මගේ, ආරම්භයක් සඳහා.
ජේබී

2
රැඳී සිටින්න ... තැපැල් පිටපත ක්‍රමලේඛන භාෂාවක් ද? ;)
n611x007

32

ජාවාස්ක්‍රිප්ට්

මම jslinux විසින් දේවානුභාවයෙන් javascript හි 486 emulator එකක් ලියමි. එය කොපමණ වැඩක් වනු ඇත්දැයි මා දැන සිටියේ නම්, මම කිසි විටෙකත් ආරම්භ නොකරනු ඇත, නමුත් දැන් මට එය අවසන් කිරීමට අවශ්‍යය.

එවිට මම ඔබේ අභියෝගයට මුහුණ දුන් අතර පරීක්ෂා කිරීමට 8086 වැඩසටහනක් තිබීම ගැන මම සතුටු වෙමි.

http://i.stack.imgur.com/54a6S.png

ඔබට එය සජීවීව "දැක ගත හැකිය": http://codinguncut.com/jsmachine/

ග්‍රැෆික් බෆරය මුද්‍රණය කිරීමේදී මට එක් ගැටළුවක් විය. අවකාශ තිබිය යුතු තැන, මතකයේ "00" මූලද්රව්ය අඩංගු වේ. "0x00" අවකාශය ලෙස අර්ථ දැක්වීම නිවැරදිද? නැතහොත් මගේ ඉමුලේටරයේ දෝෂයක් තිබේද?

චියර්ස්,

ජොහැන්නස්


මෙම අභියෝගයේ දී හස්කල් ප්‍රතිචාරයෙන් පසුව මම නැරඹූ ඔබගේ තිර විකාශනයන්ගෙන් ඔබේ නම මම දනිමි (මම ජාවාස්ක්‍රිප්ට් හි x86 ඉමුලේටරයක් ​​ද ආරම්භ කළෙමි). ඔව්, ශුන්‍ය බයිට් අවකාශයක් ලෙස දිස්විය යුතුය. මම ඔබගේ සටහනට තිර රුවද එක් කර ඇත්තෙමි. +1 කෙසේ වෙතත් :-)
පිටපත් කරන්න

O ජොහැන්නස් මට mycpu-min.js කේතය හරහා ඉක්මණින් බැලීමට හැකි විය. මට කිව හැකි දෙයින් cpux86.js (FB හි jslinux හි) අදහස් කිහිපයක් පමණක් භාවිතා කර ඇත. සුභ පැතුම්! හොඳ රැකියාවක්. සම්පාදනය නොකළ mycpu.js කොහේ හෝ දැකීමට අවස්ථාවක් තිබේද? Github.com/codinguncut හි
යවුන් යකිමොවිච්

Ay යහෙන් යකිමොවිච් නැත, මම කිසිදු jslinux කේතයක් නැවත භාවිතා කර නොමැත. මම මේ වන විට සියලුම උපදෙස් 286 us ණ පේජිං සහ ඛණ්ඩනය (mmu) ක්‍රියාත්මක කර ඇත. මගේ සැලසුම වූයේ ජීපීඑල් යටතේ කේතය මුදා හැරීමයි, නමුත් මම ඇත්ත වශයෙන්ම ෆ්‍රීඩෝස් හෝ රියාක්ටෝස් ධාවනය කිරීමේ අදහස වාණිජකරණය කිරීමට කැමතියි, එබැවින් බලපත්‍ර ලබා ගැනීම පිළිබඳව මට තවමත් විශ්වාසයක් නැත. සත්යය නම්, සම්පූර්ණ මතකය mgmt ක්රියාත්මක කිරීමට මට දිගු කාලයක් ගතවනු ඇත. ඉන්පසු එය වේගයෙන් ධාවනය කිරීමට දිගු කාලයක් ගතවේ. මම අනිවාර්යයෙන්ම github.com/codinguncut හි බෙදා ගන්නෙමි. ඔබගේ ප්‍රතිපෝෂණයට ස්තූතියි, ජොහැන්නස්
තරල

1
මා සඳහා සබැඳිය කැඩී ඇත. (වින්ඩෝස් 8 හි IE)
කොනෝර් ඕ බ්‍රයන්

මෙය ඉතා ප්‍රමාදයි. අක්ෂර ශුන්‍යය වීඩියෝ RAM හි තවත් අවකාශයකි.
යෝෂුවා

30

සී ++

මෙම කේත අභියෝගය සඳහා අපගේ ප්‍රවේශය ඉදිරිපත් කිරීමට මම කැමතියි. එය c ++ වලින් ලියා ඇති අතර පරීක්ෂණ වැඩසටහන පරිපූර්ණව ක්‍රියාත්මක කරයි. අපි එක් බයිට් ඔප් කේත සහ මූලික කොටස් වලින් 90% ක් ක්‍රියාත්මක කර ඇත්තෙමු (සමහර ඒවා අක්‍රීය කර ඇත්තේ එය පරීක්ෂණ වැඩසටහන සමඟ ක්‍රියා නොකරන නිසාය).

වැඩසටහන ලිවීම: http://davecarruth.com/index.php/2012/04/15/creating-an-8086-emulator

බ්ලොග් පෝස්ට් අවසානයේ ඔබට සිප් ගොනුවක කේතය සොයාගත හැකිය.

පරීක්ෂණ වැඩසටහන ක්‍රියාත්මක කරන තිර රුව: රූප විස්තරය මෙහි ඇතුළත් කරන්න

මේ සඳහා සෑහෙන කාලයක් ගතවිය ... ඔබට කිසියම් ප්‍රශ්නයක් හෝ අදහස් තිබේ නම් මට පණිවුඩයක් යැවීමට නිදහස් වන්න. එය නිසැකවම හවුල්කාර වැඩසටහන්කරණයේ විශිෂ්ට ව්‍යායාමයක් විය.


3
මෙම අභියෝගය පිළිබඳව මිනිසුන් විනෝද වන විට එය සැමවිටම හොඳයි :) සටහන් කිහිපයක් පමණි: මගේ පරීක්ෂණ වැඩසටහන සියලු කොටස් ශුන්‍ය කළ විට ක්‍රියා කළ යුතුය (සහ පරීක්ෂා කරන ලදි). ඔබගේ සමහර කේත දෙස බලන විට, ret immඋපදෙස් වැරදියි ( මෙහි බලන්න ) එවිට ඔබට 0xffකණ්ඩායම මඟ හැරී ඇත . ඔබගේ දෝෂ පණිවිඩ වලට මම කැමතියි: විසි කරන්න "ක්ෂණික වටිනාකමට වටිනාකමක් ගබඩා කළ නොහැක, පසුබෑම.";
පිටපත් කරන්න

පරීක්ෂණ වැඩසටහන සමඟ අපට ප්‍රධාන ගැටළු දෙකක් තිබුණි: 1) ඛණ්ඩනය - ඇමතුමක් ඇති විට අපි සීඑස් එක තොගයට තල්ලු කරමින් සිටියෙමු ... පරීක්ෂණ වැඩසටහනේ එක් කාර්යයක් මෙයට කැමති නැත. 2) පරීක්ෂණ වැඩසටහන අපේ මතකය ශුන්‍යයට ආරම්භ කරනු ඇතැයි අපේක්ෂා කළේය. කෙසේ වෙතත්, අපට බොහෝ විනෝදයක් ලැබුණි, පළ කිරීම ගැන බොහෝම ස්තූතියි!
ඩේව් සී

ඔබ එහි වැරැද්දක් කර ඇති: ජම්පර් අසල ( 0xE8 ) csලේඛනය තල්ලු නොකරන්න
පිටපත

ඒක තමයි ප්‍රශ්නය, හොඳ ඇල්ලීම! ඔබ 8086 සමඟ ඉතා පළපුරුදු බවක් පෙනේ, ඔබ ඒ සඳහා වැඩසටහන් කළාද?
ඩේව් සී

1
මම ඇත්ත වශයෙන්ම x86 ඉමියුලේටර් ව්‍යාපෘතියක වැඩ කරමින් සිටිමි. එය ෆ්‍රීඩෝස් ඉතා හොඳින් ක්‍රියාත්මක වන අතර මම දැනට සම්පූර්ණ බිට් 32 සහාය මත වැඩ කරමි; එය වෙනත් පෝස්ටර් වලට සාධාරණ නොවන නිසා මෙහි පළ නොකළේය (සහ ප්‍රභව කේතය තරමක් අවුල් වී ඇත).
පිටපත් කරන්න

28

සී

විශාල අභියෝගයක් සහ මගේ පළමු එක. මම ගිණුමක් නිර්මාණය කළේ අභියෝගය මා තුළ කුතුහලයක් ඇති කළ නිසා ය. අවාසිය නම් මට සැබෑ, ගෙවීම්, ක්‍රමලේඛන වැඩ කිරීමට සිදු වූ විට මට අභියෝගය ගැන සිතීම නතර කළ නොහැකි වීමයි.

සම්පූර්ණ 8086 ඉමියුලේෂන් ධාවනයක් ලබා ගැනීමට මට බලකෙරේ, නමුත් එය තවත් අභියෝගයකි ;-)

කේතය ANSI-C හි ලියා ඇත, එබැවින් .c ගොනු එකට සම්පාදනය කරන්න / සම්බන්ධ කරන්න, කෝඩ්ගොල්ෆ් ද්විමය හරහා ගොස් යන්න.

ප්‍රභවය සිප් කර ඇත

රූප විස්තරය මෙහි ඇතුළත් කරන්න


හොඳ රැකියාවක් රිච්ටීඑක්ස්!
ඩේව් සී

ස්තූතියි ඩේව්. ඔබත්. මම ආරම්භ කරන විට කේතය හැකි තරම් කුඩා කිරීමේ අපේක්ෂාව මට නොතේරුණි, නමුත් එය තවමත් අභියෝගයකි.
රිච් ටීඑක්ස්

+1 රැගෙන යාමේ ධජය ක්‍රියා කරන්නේ කෙසේදැයි දැන ගැනීමට මම ඔබේ කේතය දෙස බැලුවෙමි.
luser droog

සබැඳිය මට පහලයි.
ටයිලෝ

25

සී ++ 1064 පේළි

අපූරු ව්‍යාපෘතිය. මම මීට වසර ගණනාවකට පෙර ඉන්ටෙලිවිෂන් ඉමුලේටරයක් කළා, ඒ නිසා මගේ මාංශ පේශි නැවත නැමීමට ලැබීම සතුටක්.

සතියක පමණ වැඩ කිරීමෙන් පසු, මෙය සිදු වූ විට මට තවත් කලබල විය නොහැක.

.........
╤╤╤╤╤╤╤╤╤╤╤╤╤╤
0123456789:;? @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\] ^ _ `abcdefghijklmnopqrstuvwxyz {|} ~


################################ ##########################
################################ #####################
    0 0 0 0 0 0 0 0 0 0 0 0 0

    0 1 4 9 ♠ a ♣ b ♠ cd ♦ f ☺h `§☺b, ♦ d E f` ♠ i ↓ 8 b 8 ♠ e Y h ↑ = b = ☺f`

    2 3 4 5 6 7 8 9 අ ☺a ☻a a ♦ a ab a a ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
 c ☺c ☻c c c ♣ c ♠ c cc cd ☺d ☻d ♥ d ♦ d de d d d de de
 ee ef ☺f ☻f ♥ f ♦ f f f ff gg ☻g ♥ g ♦ g ♣ g gg gggh ☺h ☻h
h ♦ h h ♠ h h hi ☺i i i ♦ i ♣ i ii i `

පසුව ටිකක් නිදොස් කිරීම සහ ... ෂාසාම්! රූප විස්තරය මෙහි ඇතුළත් කරන්න

එසේම, 8086 දිගුවකින් තොරව මුල් පරීක්ෂණ වැඩසටහන නැවත ගොඩනඟා ගත්තෙමි, මන්ද මගේ ඉමියුලේටරය 8086 ට සත්‍ය ලෙස ගොඩනඟා ගැනීමට අවශ්‍ය වූ අතර කිසිදු අමතර උපදෙස් වලට නොරැවටෙන්න. මෙහි කේතයට link ජු සබැඳිය: Zip ගොනුව .

හරි, මම මේ සමඟ ඕනෑවට වඩා විනෝද වෙමි. මම මතකය සහ තිර කළමනාකරණය බිඳ දැමුවෙමි, දැන් තිර බෆරය ලියා ඇති විට තිරය යාවත්කාලීන වේ. මම වීඩියෝවක් හැදුවා :)

http://www.youtube.com/watch?v=qnAssaTpmnA

යාවත්කාලීනයන්: ඛණ්ඩනය කිරීමේ පළමු වර්‍ගය ක්‍රියාත්මක වේ. උපදෙස් ඉතා ස්වල්පයක් ක්‍රියාත්මක කර ඇත, නමුත් සීඑස් / ඩීඑස් සහ එස්එස් වටා ගෙන යාමෙන් මම එය පරීක්ෂා කළෙමි, සෑම දෙයක්ම තවමත් හොඳින් ක්‍රියාත්මක වේ.

මුලික බාධා කිරීම් හැසිරවීම ද එක් කරන ලදි. ඉතා මුලිකයි. නමුත් මම නූල් මුද්‍රණය කිරීම සඳහා int 21h ක්‍රියාත්මක කළෙමි. පරීක්ෂණ ප්‍රභවයට පේළි කිහිපයක් එකතු කර එයද උඩුගත කරන ලදි.

start:
    sti
    mov ah, 9
    mov dx, joetext
    int 21h
...

joetext:
    db 'This was printed by int 21h$', 0

රූප විස්තරය මෙහි ඇතුළත් කරන්න

යමෙකුට තරමක් සරල එකලස් කේතයක් තිබේ නම් එය කොටස් පරීක්ෂා කරනු ඇත, මම එය සමඟ සෙල්ලම් කිරීමට කැමතියි.

මම මෙය කොතරම් දුරට ගෙන යා යුතුදැයි වටහා ගැනීමට උත්සාහ කරමි. සම්පූර්ණ CPU අනුකරණය? VGA මාදිලිය? දැන් මම ඩොස්බොක්ස් ලියමි.

12/6: එය පරීක්ෂා කරන්න, VGA මාදිලිය!

රූප විස්තරය මෙහි ඇතුළත් කරන්න


ලියාපදිංචිය අවශ්‍ය නොවන නිදහස් වෙබ් අඩවියක ඔබේ කේතය පළ කිරීමට ඔබට අවස්ථාවක් තිබේද? ස්තූතියි
ඩේව් සී

ලියාපදිංචි වීම අවශ්‍ය බව මම දැන සිටියේ නැත. ඒ ගැන කණගාටුයි! මම අද රෑ ගෙදර ආවම ඒක කරන්න උත්සාහ කරන්නම්.
ජෝෆිෂ්

Ave ඩේව්සී, නවතම සංස්කරණය පරීක්ෂා කරන්න.
ජෝෆිෂ්

ඔටුවන් ෆෝර්ට් වරායක් තිබේදැයි මම කල්පනා කරමි. එය කොටස් පරීක්ෂා කරනු ඇත.
luser droog

ඒක නියමයි! +1 නැවතත්. btw, එහි වන ඔටුවා පිටතට ක 8086 වරාය bradrodriguez.com/papers/index.html .
luser droog

25

සී ++ - පේළි 4455

නැහැ, මම ප්‍රශ්නයේ අවශ්‍යතා පමණක් කළේ නැහැ. මම පෙර නොවූ විරූ ඔප්කෝඩ් 16 ක් ඇතුළුව ENTIRE 8086 කළා. එම ඔප්කෝඩ් හදුනා ගැනීමට reenigne උදව් විය.

https://github.com/Alegend45/IBM5150


පේළි 4455 ගොනුව කොහෙද? ඔහ්, මම ඒක හොයාගත්තා. මෙම #include "cpu.h"බලන්න අමාරුයි.
luser droog

2
(w) ශුද්ධ ස්විච් ප්‍රකාශය!
luser droog

ඔව්, එය තවත් නරක අතට හැරීමට ආසන්නයි, මන්ද මම NEC V20 සහයද ඇතුළත් කිරීමට සූදානම්ව සිටිමි.
ඩාරියස් ගෝඩ්

මම රෙනින්ගේ බ්ලොග් අඩවිය හරහා බැලුවෙමි . මෙම අමතර ඔප්කෝඩ් ගැන කිසිවක් සොයාගත නොහැක. එය කොතැනක හෝ මාර්ගගතව තිබේද?
luser droog

1
ඔහු ටික කලකින් ඔහුගේ බ්ලොගය යාවත්කාලීන කර නැත. ඔහු එෆ්නෙට් හි # ibm5150 හි සිටී, නමුත් ඔබට ඔහුගෙන් එතැනින් විමසන්න.
ඩාරියස් ගෝඩ්

20

ජාවාස්ක්‍රිප්ට් - පේළි 4,404

මගේම ඉමුලේටරය සඳහා තොරතුරු ගවේෂණය කිරීමේදී මම මෙම තනතුරට බාධා කළෙමි. මෙම කෝඩ්ගොල්ෆ් සටහන මට කිසිසේත්ම මිල කළ නොහැකි ය. නිදර්ශන වැඩසටහන සහ ආශ්‍රිත එකලස් කිරීම මඟින් පහසුවෙන් නිදොස්කරණය කර සිදුවන්නේ කුමක්දැයි බැලීමට හැකි විය.

ඔබට ස්තුතියි!!!

මෙන්න මගේ ජාවාස්ක්‍රිප්ට් 8086 ඉමුලේටරයේ පළමු අනුවාදය.

සම්පූර්ණ ධාවනය

විශේෂාංග:

  • මෙම අභියෝගය සඳහා අවශ්‍ය සියලුම ඔප්කෝඩ් සහ කේත කිරීමට පහසු වන තරමට සමාන අමතර කිහිපයක්
  • අර්ධ වශයෙන් ක්‍රියාකාරී පෙළ ප්‍රකාරය (80x25) වීඩියෝව (තවමත් බාධා කිරීම් නොමැත)
  • ක්‍රියාකාරී තොගය
  • මූලික (ඛණ්ඩනය නොකළ) මතකය
  • ඉතා හොඳ නිදොස්කරණය (මෙය තිබිය යුතුය)
  • කේත පිටුව 437 අකුරු කට්ටලය බිට්මැප් නිරූපණයකින් ගතිකව පටවනු ලැබේ

නිරූපණය

මට සබැඳි නිරූපණයක් ඇත, එය සමඟ සෙල්ලම් කිරීමට නිදහස්ව සිටින්න, ඔබ දෝෂ සොයා ගන්නේ නම් මට දන්වන්න :)

http://js86emu.chadrempp.com/

කෝඩ්ගොල්ෆ් වැඩසටහන ක්‍රියාත්මක කිරීමට

1) සැකසුම් බොත්තම මත ක්ලික් කරන්න

රූප විස්තරය මෙහි ඇතුළත් කරන්න

2) පසුව පැටවීම ක්ලික් කරන්න (ඔබට ක්‍රමලේඛය හරහා පියවර තැබීම වැනි නිදොස් කිරීමේ විකල්ප සමඟ සෙල්ලම් කළ හැකිය). කෝඩ්ගොල්ෆ් වැඩසටහන මේ මොහොතේ ඇති එකම එකකි, මම වැඩිපුර මාර්ගගතව ලබා ගැනීමට කටයුතු කරමින් සිටිමි.

රූප විස්තරය මෙහි ඇතුළත් කරන්න

මූලාශ්රය

සම්පූර්ණ මූලාශ්‍රය මෙහි. https://github.com/crempp/js86emu

8086 අනුකරණයේ ධෛර්යය මෙහි ඇලවීමට මම උත්සාහ කළෙමි (දොර දොරටුව යෝජනා කළ පරිදි) නමුත් එය අක්ෂර සීමාව ඉක්මවා ගියේය ("ශරීරය අක්ෂර 30000 කට සීමා වේ; ඔබ 158,272 ට ඇතුල් විය").

මෙන්න මම මෙහි ඇලවීමට යන කේතයට ඉක්මන් සබැඳියක් - https://github.com/crempp/js86emu/blob/39dbcb7106a0aaf59e003cd7f722acb4b6923d87/src/js/emu/cpus/8086.js

*Edit - updated for new demo and repo location


නියමයි! කෙසේ වෙතත්, අපගේ පෝස්ට් ස්වයං අන්තර්ගතයට වඩා අපි කැමති බැවින් කේතය ඔබගේ ලිපියේම තිබේ නම් එය වඩාත් සුදුසු වේ.
දොරක්නොබ්

O ඩෝර්ක්නොබ්, මට තේරෙන්නේ නැහැ මට තේරෙනවා කියලා. කේත පේළි 4,400 ක් පේළියේ පළ කිරීමට ඔබ කැමතිද?
crempp

උම්මු ... මම එය තේරුම් ගත්තේ නැත බව දීර්ඝ. එය උපරිම අක්ෂර සීමාව තුළට ගැලපේද? එසේ නම්, ඔව්, ඔබගේ තනතුර ස්වයං අන්තර්ගත නම් එය ඉතා හොඳ වේ. ස්තූතියි! :-)
දොරක්නොබ්

13

ජාවා

මට මෙතරම් කාලයක් තිස්සේ මෙම අභියෝගය කිරීමට අවශ්‍ය වූ අතර අවසානයේ මම ඒ සඳහා කාලය ගත්තා. එය මෙතෙක් අපූරු අත්දැකීමක් වූ අතර මම එය අවසන් කළ බව අනුමාන කිරීමට ආඩම්බර වෙමි.

පරීක්ෂණ වැඩසටහන් ප්‍රතිදානය

මූලාශ්රය

ප්‍රභව කේතය GitHub හි NeatMonster / Intel8086 හි ඇත. හොලි 8086 පවුලේ පරිශීලක අත්පොතේ ආධාරයෙන් මම සෑම දෙයක්ම ලේඛනගත කිරීමට උත්සාහ කර ඇත්තෙමි .

නැතිවූ සියලුම ඔප්කෝඩ් සහ විශේෂාංග ක්‍රියාත්මක කිරීමට මම අදහස් කරමි, එබැවින් ඔබට නිකුතුව 1.0 පරීක්ෂා කිරීමට අවශ්‍ය විය හැකිය මෙම අභියෝගයට අවශ්‍ය ඒවා පමණක් සහිත අනුවාදයක් සඳහා .

@ කොපී වලට බොහෝ ස්තූතියි!


13

පොදු ලිප්ස් - 580 ස්ථානය (හිස් රේඛා සහ අදහස් 442 w / o)

පොදු ලිප්ස් ඉගෙන ගැනීමට නිදහසට කරුණක් ලෙස මම මෙම අභියෝගය භාවිතා කළෙමි. ප්‍රති result ලය මෙන්න:

;;; Program settings

(defparameter *disasm* nil "Whether to disassemble")

(defmacro disasm-instr (on-disasm &body body)
  `(if *disasm*
       ,on-disasm
       (progn ,@body)))

;;; State variables

(defparameter *ram* (make-array (* 64 1024) :initial-element 0 :element-type '(unsigned-byte 8)) "Primary segment")
(defparameter *stack* (make-array (* 64 1024) :initial-element 0 :element-type '(unsigned-byte 8)) "Stack segment")
(defparameter *flags* '(:cf 0 :sf 0 :zf 0) "Flags")
(defparameter *registers* '(:ax 0 :bx 0 :cx 0 :dx 0 :bp 0 :sp #x100 :si 0 :di 0) "Registers")
(defparameter *ip* 0 "Instruction pointer")
(defparameter *has-carried* nil "Whether the last wraparound changed the value")
(defparameter *advance* 0 "Bytes to advance IP by after an operation")

;;; Constants

(defconstant +byte-register-to-word+ '(:al (:ax nil) :ah (:ax t) :bl (:bx nil) :bh (:bx t) :cl (:cx nil) :ch (:cx t) :dl (:dx nil) :dh (:dx t)) "Mapping from byte registers to word registers")
(defconstant +bits-to-register+ '(:ax :cx :dx :bx :sp :bp :si :di) "Mapping from index to word register")
(defconstant +bits-to-byte-register+ '(:al :cl :dl :bl :ah :ch :dh :bh) "Mapping from index to byte register")

;;; Constant mappings

(defun bits->word-reg (bits)
  (elt +bits-to-register+ bits))

(defun bits->byte-reg (bits)
  (elt +bits-to-byte-register+ bits))

(defun address-for-r/m (mod-bits r/m-bits)
  (disasm-instr
      (if (and (= mod-bits #b00) (= r/m-bits #b110))
      (list :disp (peek-at-word))
      (case r/m-bits
        (#b000 (list :base :bx :index :si))
        (#b001 (list :base :bx :index :di))
        (#b010 (list :base :bp :index :si))
        (#b011 (list :base :bp :index :di))
        (#b100 (list :index :si))
        (#b101 (list :index :di))
        (#b110 (list :base :bp))
        (#b111 (list :base :bx))))
    (if (and (= mod-bits #b00) (= r/m-bits #b110))
    (peek-at-word)
    (case r/m-bits
      (#b000 (+ (register :bx) (register :si)))
      (#b001 (+ (register :bx) (register :di)))
      (#b010 (+ (register :bp) (register :si)))
      (#b011 (+ (register :bp) (register :di)))
      (#b100 (register :si))
      (#b101 (register :di))
      (#b110 (register :bp))
      (#b111 (register :bx))))))

;;; Convenience functions

(defun reverse-little-endian (low high)
  "Reverse a little-endian number."
  (+ low (ash high 8)))

(defun negative-p (value is-word)
  (or (if is-word (>= value #x8000) (>= value #x80)) (< value 0)))

(defun twos-complement (value is-word)
  (if (negative-p value is-word)
      (- (1+ (logxor value (if is-word #xffff #xff))))
      value))

(defun wrap-carry (value is-word)
  "Wrap around an carried value."
  (let ((carry (if is-word (>= value #x10000) (>= value #x100))))
    (setf *has-carried* carry)
    (if carry
    (if is-word (mod value #x10000) (mod value #x100))
    value)))

;;; setf-able locations

(defun register (reg)
  (disasm-instr reg
    (getf *registers* reg)))

(defun set-reg (reg value)
  (setf (getf *registers* reg) (wrap-carry value t)))

(defsetf register set-reg)

(defun byte-register (reg)
  (disasm-instr reg
    (let* ((register-to-word (getf +byte-register-to-word+ reg)) (word (first register-to-word)))
      (if (second register-to-word)
      (ash (register word) -8)
      (logand (register word) #x00ff)))))

(defun set-byte-reg (reg value)
  (let* ((register-to-word (getf +byte-register-to-word+ reg)) (word (first register-to-word)) (wrapped-value (wrap-carry value nil)))
    (if (second register-to-word)
    (setf (register word) (+ (ash wrapped-value 8) (logand (register word) #x00ff)))
    (setf (register word) (+ wrapped-value (logand (register word) #xff00))))))

(defsetf byte-register set-byte-reg)

(defun flag (name)
  (getf *flags* name))

(defun set-flag (name value)
  (setf (getf *flags* name) value))

(defsetf flag set-flag)

(defun flag-p (name)
  (= (flag name) 1))

(defun set-flag-p (name is-set)
  (setf (flag name) (if is-set 1 0)))

(defsetf flag-p set-flag-p)

(defun byte-in-ram (location segment)
  "Read a byte from a RAM segment."
  (elt segment location))

(defsetf byte-in-ram (location segment) (value)
  "Write a byte to a RAM segment."
  `(setf (elt ,segment ,location) ,value))

(defun word-in-ram (location segment)
  "Read a word from a RAM segment."
  (reverse-little-endian (elt segment location) (elt segment (1+ location))))

(defsetf word-in-ram (location segment) (value)
  "Write a word to a RAM segment."
  `(progn
     (setf (elt ,segment ,location) (logand ,value #x00ff))
     (setf (elt ,segment (1+ ,location)) (ash (logand ,value #xff00) -8))))

(defun indirect-address (mod-bits r/m-bits is-word)
  "Read from an indirect address."
  (disasm-instr
      (if (= mod-bits #b11) (register (if is-word (bits->word-reg r/m-bits) (bits->byte-reg r/m-bits)))
      (let ((base-index (address-for-r/m mod-bits r/m-bits)))
        (unless (getf base-index :disp)
          (setf (getf base-index :disp)
            (case mod-bits
              (#b00 0)
              (#b01 (next-instruction))
              (#b10 (next-word)))))
        base-index))
    (let ((address-base (address-for-r/m mod-bits r/m-bits)))
      (case mod-bits
    (#b00 (if is-word (word-in-ram address-base *ram*) (byte-in-ram address-base *ram*)))
    (#b01 (if is-word (word-in-ram (+ address-base (peek-at-instruction)) *ram*) (byte-in-ram (+ address-base (peek-at-instruction)) *ram*)))
    (#b10 (if is-word (word-in-ram (+ address-base (peek-at-word)) *ram*) (byte-in-ram (+ address-base (peek-at-word)) *ram*)))
    (#b11 (if is-word (register (bits->word-reg r/m-bits)) (byte-register (bits->byte-reg r/m-bits))))))))

(defsetf indirect-address (mod-bits r/m-bits is-word) (value)
  "Write to an indirect address."
  `(let ((address-base (address-for-r/m ,mod-bits ,r/m-bits)))
    (case ,mod-bits
      (#b00 (if ,is-word (setf (word-in-ram address-base *ram*) ,value) (setf (byte-in-ram address-base *ram*) ,value)))
      (#b01 (if ,is-word (setf (word-in-ram (+ address-base (peek-at-instruction)) *ram*) ,value) (setf (byte-in-ram (+ address-base (peek-at-instruction)) *ram*) ,value)))
      (#b10 (if ,is-word (setf (word-in-ram (+ address-base (peek-at-word)) *ram*) ,value) (setf (byte-in-ram (+ address-base (peek-at-word)) *ram*) ,value)))
      (#b11 (if ,is-word (setf (register (bits->word-reg ,r/m-bits)) ,value) (setf (byte-register (bits->byte-reg ,r/m-bits)) ,value))))))

;;; Instruction loader

(defun load-instructions-into-ram (instrs)
  (setf *ip* 0)
  (setf (subseq *ram* 0 #x7fff) instrs)
  (length instrs))

(defun next-instruction ()
  (incf *ip*)
  (elt *ram* (1- *ip*)))

(defun next-word ()
  (reverse-little-endian (next-instruction) (next-instruction)))

(defun peek-at-instruction (&optional (forward 0))
  (incf *advance*)
  (elt *ram* (+ *ip* forward)))

(defun peek-at-word ()
  (reverse-little-endian (peek-at-instruction) (peek-at-instruction 1)))

(defun advance-ip ()
  (incf *ip* *advance*)
  (setf *advance* 0))

(defun advance-ip-ahead-of-indirect-address (mod-bits r/m-bits)
  (cond
    ((or (and (= mod-bits #b00) (= r/m-bits #b110)) (= mod-bits #b10)) 2)
    ((= mod-bits #b01) 1)
    (t 0)))

(defun next-instruction-ahead-of-indirect-address (mod-bits r/m-bits)
  (let ((*ip* *ip*))
    (incf *ip* (advance-ip-ahead-of-indirect-address mod-bits r/m-bits))
    (incf *advance*)
    (next-instruction)))

(defun next-word-ahead-of-indirect-address (mod-bits r/m-bits)
  (let ((*ip* *ip*))
    (incf *ip* (advance-ip-ahead-of-indirect-address mod-bits r/m-bits))
    (incf *advance* 2)
    (next-word)))

;;; Memory access

(defun read-word-from-ram (loc &optional (segment *ram*))
  (word-in-ram loc segment))

(defun write-word-to-ram (loc word &optional (segment *ram*))
  (setf (word-in-ram loc segment) word))

(defun push-to-stack (value)
  (decf (register :sp) 2)
  (write-word-to-ram (register :sp) value *stack*))

(defun pop-from-stack ()
  (incf (register :sp) 2)
  (read-word-from-ram (- (register :sp) 2) *stack*))

;;; Flag effects

(defun set-cf-on-add (value)
  (setf (flag-p :cf) *has-carried*)
  value)

(defun set-cf-on-sub (value1 value2)
  (setf (flag-p :cf) (> value2 value1))
  (- value1 value2))

(defun set-sf-on-op (value is-word)
  (setf (flag-p :sf) (negative-p value is-word))
  value)

(defun set-zf-on-op (value)
  (setf (flag-p :zf) (= value 0))
  value)

;;; Operations

;; Context wrappers

(defun with-one-byte-opcode-register (opcode fn)
  (let ((reg (bits->word-reg (mod opcode #x08))))
    (funcall fn reg)))

(defmacro with-mod-r/m-byte (&body body)
  `(let* ((mod-r/m (next-instruction)) (r/m-bits (logand mod-r/m #b00000111)) (mod-bits (ash (logand mod-r/m #b11000000) -6)) (reg-bits (ash (logand mod-r/m #b00111000) -3)))
     ,@body))

(defmacro with-in-place-mod (dest mod-bits r/m-bits &body body)
  `(progn
     ,@body
     (when (equal (car ',dest) 'indirect-address)
       (decf *advance* (advance-ip-ahead-of-indirect-address ,mod-bits ,r/m-bits)))))

;; Templates

(defmacro mov (src dest)
  `(disasm-instr (list "mov" :src ,src :dest ,dest)
     (setf ,dest ,src)))

(defmacro xchg (op1 op2)
  `(disasm-instr (list "xchg" :op1 ,op1 :op2 ,op2)
     (rotatef ,op1 ,op2)))

(defmacro inc (op1 is-word)
  `(disasm-instr (list "inc" :op1 ,op1)
     (set-sf-on-op (set-zf-on-op (incf ,op1)) ,is-word)))

(defmacro dec (op1 is-word)
  `(disasm-instr (list "dec" :op1 ,op1)
     (set-sf-on-op (set-zf-on-op (decf ,op1)) ,is-word)))

;; Group handling

(defmacro parse-group-byte-pair (opcode operation mod-bits r/m-bits)
  `(,operation ,mod-bits ,r/m-bits (oddp ,opcode)))

(defmacro parse-group-opcode (&body body)
  `(with-mod-r/m-byte
     (case reg-bits
       ,@body)))

;; One-byte opcodes on registers

(defun clear-carry-flag ()
  (disasm-instr '("clc")
    (setf (flag-p :cf) nil)))

(defun set-carry-flag ()
  (disasm-instr '("stc")
    (setf (flag-p :cf) t)))

(defun push-register (reg)
  (disasm-instr (list "push" :src reg)
    (push-to-stack (register reg))))

(defun pop-to-register (reg)
  (disasm-instr (list "pop" :dest reg)
    (setf (register reg) (pop-from-stack))))

(defun inc-register (reg)
  (inc (register reg) t))

(defun dec-register (reg)
  (dec (register reg) t))

(defun xchg-register (reg)
  (disasm-instr (if (eql reg :ax) '("nop") (list "xchg" :op1 :ax :op2 reg))
    (xchg (register :ax) (register reg))))

(defun mov-byte-to-register (opcode)
  (let ((reg (bits->byte-reg (mod opcode #x08))))
    (mov (next-instruction) (byte-register reg))))

(defun mov-word-to-register (reg)
  (mov (next-word) (register reg)))

;; Flow control

(defun jmp-short ()
  (disasm-instr (list "jmp" :op1 (twos-complement (next-instruction) nil))
    (incf *ip* (twos-complement (next-instruction) nil))))

(defmacro jmp-short-conditionally (opcode condition mnemonic)
  `(let ((disp (next-instruction)))
     (if (evenp ,opcode)
       (disasm-instr (list (concatenate 'string "j" ,mnemonic) :op1 (twos-complement disp nil))
     (when ,condition
       (incf *ip* (twos-complement disp nil))))
       (disasm-instr (list (concatenate 'string "jn" ,mnemonic) :op1 (twos-complement disp nil))
     (unless ,condition
       (incf *ip* (twos-complement disp nil)))))))

(defun call-near ()
  (disasm-instr (list "call" :op1 (twos-complement (next-word) t))
    (push-to-stack (+ *ip* 2))
    (incf *ip* (twos-complement (next-word) t))))

(defun ret-from-call ()
  (disasm-instr '("ret")
    (setf *ip* (pop-from-stack))))

;; ALU

(defmacro parse-alu-opcode (opcode operation)
  `(let ((mod-8 (mod ,opcode 8)))
     (case mod-8
       (0
    (with-mod-r/m-byte
      (,operation (byte-register (bits->byte-reg reg-bits)) (indirect-address mod-bits r/m-bits nil) nil mod-bits r/m-bits)))
       (1
    (with-mod-r/m-byte
      (,operation (register (bits->word-reg reg-bits)) (indirect-address mod-bits r/m-bits t) t mod-bits r/m-bits)))
       (2
    (with-mod-r/m-byte
      (,operation (indirect-address mod-bits r/m-bits nil) (byte-register (bits->byte-reg reg-bits)) nil)))
       (3
    (with-mod-r/m-byte
      (,operation (indirect-address mod-bits r/m-bits t) (register (bits->word-reg reg-bits)) t)))
       (4
    (,operation (next-instruction) (byte-register :al) nil))
       (5
    (,operation (next-word) (register :ax) t)))))

(defmacro add-without-carry (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "add" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (set-zf-on-op (set-sf-on-op (set-cf-on-add (incf ,dest ,src)) ,is-word)))))

(defmacro add-with-carry (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "adc" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (set-zf-on-op (set-sf-on-op (set-cf-on-add (incf ,dest (+ ,src (flag :cf)))) ,is-word)))))

(defmacro sub-without-borrow (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "sub" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (let ((src-value ,src))
     (set-zf-on-op (set-sf-on-op (set-cf-on-sub (+ (decf ,dest src-value) src-value) src-value) ,is-word))))))

(defmacro sub-with-borrow (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "sbb" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (let ((src-plus-cf (+ ,src (flag :cf))))
     (set-zf-on-op (set-sf-on-op (set-cf-on-sub (+ (decf ,dest src-plus-cf) src-plus-cf) src-plus-cf) ,is-word))))))

(defmacro cmp-operation (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "cmp" :src ,src :dest ,dest)
     (set-zf-on-op (set-sf-on-op (set-cf-on-sub ,dest ,src) ,is-word))))

(defmacro and-operation (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "and" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (set-zf-on-op (set-sf-on-op (setf ,dest (logand ,src ,dest)) ,is-word))
       (setf (flag-p :cf) nil))))

(defmacro or-operation (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "or" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (set-zf-on-op (set-sf-on-op (setf ,dest (logior ,src ,dest)) ,is-word))
       (setf (flag-p :cf) nil))))

(defmacro xor-operation (src dest is-word &optional mod-bits r/m-bits)
  `(disasm-instr (list "xor" :src ,src :dest ,dest)
     (with-in-place-mod ,dest ,mod-bits ,r/m-bits
       (set-zf-on-op (set-sf-on-op (setf ,dest (logxor ,src ,dest)) ,is-word))
       (setf (flag-p :cf) nil))))

(defmacro parse-group1-byte (opcode operation mod-bits r/m-bits)
  `(case (mod ,opcode 4)
    (0 (,operation (next-instruction-ahead-of-indirect-address ,mod-bits ,r/m-bits) (indirect-address ,mod-bits ,r/m-bits nil) nil mod-bits r/m-bits))
    (1 (,operation (next-word-ahead-of-indirect-address ,mod-bits ,r/m-bits) (indirect-address ,mod-bits ,r/m-bits t) t mod-bits r/m-bits))
    (3 (,operation (twos-complement (next-instruction-ahead-of-indirect-address ,mod-bits ,r/m-bits) nil) (indirect-address ,mod-bits ,r/m-bits t) t mod-bits r/m-bits))))

(defmacro parse-group1-opcode (opcode)
  `(parse-group-opcode
     (0 (parse-group1-byte ,opcode add-without-carry mod-bits r/m-bits))
     (1 (parse-group1-byte ,opcode or-operation mod-bits r/m-bits))
     (2 (parse-group1-byte ,opcode add-with-carry mod-bits r/m-bits))
     (3 (parse-group1-byte ,opcode sub-with-borrow mod-bits r/m-bits))
     (4 (parse-group1-byte ,opcode and-operation mod-bits r/m-bits))
     (5 (parse-group1-byte ,opcode sub-without-borrow mod-bits r/m-bits))
     (6 (parse-group1-byte ,opcode xor-operation mod-bits r/m-bits))
     (7 (parse-group1-byte ,opcode cmp-operation mod-bits r/m-bits))))

;; Memory and register mov/xchg

(defun xchg-memory-register (opcode)
  (let ((is-word (oddp opcode)))
    (with-mod-r/m-byte
      (if is-word
      (xchg (register (bits->word-reg reg-bits)) (indirect-address mod-bits r/m-bits is-word))
      (xchg (byte-register (bits->byte-reg reg-bits)) (indirect-address mod-bits r/m-bits is-word))))))

(defmacro mov-immediate-to-memory (mod-bits r/m-bits is-word)
  `(if ,is-word
       (mov (next-word-ahead-of-indirect-address ,mod-bits ,r/m-bits) (indirect-address ,mod-bits ,r/m-bits t))
       (mov (next-instruction-ahead-of-indirect-address ,mod-bits ,r/m-bits) (indirect-address ,mod-bits ,r/m-bits nil))))

(defmacro parse-group11-opcode (opcode)
  `(parse-group-opcode
     (0 (parse-group-byte-pair ,opcode mov-immediate-to-memory mod-bits r/m-bits))))

(defmacro parse-mov-opcode (opcode)
  `(let ((mod-4 (mod ,opcode 4)))
     (with-mod-r/m-byte
       (case mod-4
     (0
      (mov (byte-register (bits->byte-reg reg-bits)) (indirect-address mod-bits r/m-bits nil)))
     (1
      (mov (register (bits->word-reg reg-bits)) (indirect-address mod-bits r/m-bits t)))
     (2
      (mov (indirect-address mod-bits r/m-bits nil) (byte-register (bits->byte-reg reg-bits))))
     (3
      (mov (indirect-address mod-bits r/m-bits t) (register (bits->word-reg reg-bits))))))))

;; Group 4/5 (inc/dec on EAs)

(defmacro inc-indirect (mod-bits r/m-bits is-word)
  `(inc (indirect-address ,mod-bits ,r/m-bits ,is-word) ,is-word))

(defmacro dec-indirect (mod-bits r/m-bits is-word)
  `(dec (indirect-address ,mod-bits ,r/m-bits ,is-word) ,is-word))

(defmacro parse-group4/5-opcode (opcode)
  `(parse-group-opcode
     (0 (parse-group-byte-pair ,opcode inc-indirect mod-bits r/m-bits))
     (1 (parse-group-byte-pair ,opcode dec-indirect mod-bits r/m-bits))))

;;; Opcode parsing

(defun in-paired-byte-block-p (opcode block)
  (= (truncate (/ opcode 2)) (/ block 2)))

(defun in-4-byte-block-p (opcode block)
  (= (truncate (/ opcode 4)) (/ block 4)))

(defun in-8-byte-block-p (opcode block)
  (= (truncate (/ opcode 8)) (/ block 8)))

(defun in-6-byte-block-p (opcode block)
  (and (= (truncate (/ opcode 8)) (/ block 8)) (< (mod opcode 8) 6)))

(defun parse-opcode (opcode)
  "Parse an opcode."
  (cond
    ((not opcode) (return-from parse-opcode nil))
    ((= opcode #xf4) (return-from parse-opcode '("hlt")))
    ((in-8-byte-block-p opcode #x40) (with-one-byte-opcode-register opcode #'inc-register))
    ((in-8-byte-block-p opcode #x48) (with-one-byte-opcode-register opcode #'dec-register))
    ((in-8-byte-block-p opcode #x50) (with-one-byte-opcode-register opcode #'push-register))
    ((in-8-byte-block-p opcode #x58) (with-one-byte-opcode-register opcode #'pop-to-register))
    ((in-8-byte-block-p opcode #x90) (with-one-byte-opcode-register opcode #'xchg-register))
    ((in-8-byte-block-p opcode #xb0) (mov-byte-to-register opcode))
    ((in-8-byte-block-p opcode #xb8) (with-one-byte-opcode-register opcode #'mov-word-to-register))
    ((= opcode #xf8) (clear-carry-flag))
    ((= opcode #xf9) (set-carry-flag))
    ((= opcode #xeb) (jmp-short))
    ((in-paired-byte-block-p opcode #x72) (jmp-short-conditionally opcode (flag-p :cf) "b"))
    ((in-paired-byte-block-p opcode #x74) (jmp-short-conditionally opcode (flag-p :zf) "z"))
    ((in-paired-byte-block-p opcode #x76) (jmp-short-conditionally opcode (or (flag-p :cf) (flag-p :zf)) "be"))
    ((in-paired-byte-block-p opcode #x78) (jmp-short-conditionally opcode (flag-p :sf) "s"))
    ((= opcode #xe8) (call-near))
    ((= opcode #xc3) (ret-from-call))
    ((in-6-byte-block-p opcode #x00) (parse-alu-opcode opcode add-without-carry))
    ((in-6-byte-block-p opcode #x08) (parse-alu-opcode opcode or-operation))
    ((in-6-byte-block-p opcode #x10) (parse-alu-opcode opcode add-with-carry))
    ((in-6-byte-block-p opcode #x18) (parse-alu-opcode opcode sub-with-borrow))
    ((in-6-byte-block-p opcode #x20) (parse-alu-opcode opcode and-operation))
    ((in-6-byte-block-p opcode #x28) (parse-alu-opcode opcode sub-without-borrow))
    ((in-6-byte-block-p opcode #x30) (parse-alu-opcode opcode xor-operation))
    ((in-6-byte-block-p opcode #x38) (parse-alu-opcode opcode cmp-operation))
    ((in-4-byte-block-p opcode #x80) (parse-group1-opcode opcode))
    ((in-4-byte-block-p opcode #x88) (parse-mov-opcode opcode))
    ((in-paired-byte-block-p opcode #x86) (xchg-memory-register opcode))
    ((in-paired-byte-block-p opcode #xc6) (parse-group11-opcode opcode))
    ((in-paired-byte-block-p opcode #xfe) (parse-group4/5-opcode opcode))))

;;; Main functions

(defun execute-instructions ()
  "Loop through loaded instructions."
  (loop
     for ret = (parse-opcode (next-instruction))
     until (equal ret '("hlt"))
     do (advance-ip)
     finally (return t)))

(defun disasm-instructions (instr-length)
  "Disassemble code."
  (loop
     for ret = (parse-opcode (next-instruction))
     collecting ret into disasm
     until (= *ip* instr-length)
     do (advance-ip)
     finally (return disasm)))

(defun loop-instructions (instr-length)
  (if *disasm*
      (disasm-instructions instr-length)
      (execute-instructions)))

(defun load-instructions-from-file (file)
  (with-open-file (in file :element-type '(unsigned-byte 8))
    (let ((instrs (make-array (file-length in) :element-type '(unsigned-byte 8) :initial-element 0 :adjustable t)))
      (read-sequence instrs in)
      instrs)))

(defun load-instructions (&key (file nil))
  (if file
      (load-instructions-from-file file)
      #()))

(defun print-video-ram (&key (width 80) (height 25) (stream t) (newline nil))
  (dotimes (line height)
    (dotimes (column width)
      (let ((char-at-cell (byte-in-ram (+ #x8000 (* line 80) column) *ram*)))
    (if (zerop char-at-cell)
        (format stream "~a" #\Space)
        (format stream "~a" (code-char char-at-cell)))))
    (if newline (format stream "~%"))))

(defun disasm (&key (file nil))
  (setf *disasm* t)
  (loop-instructions (load-instructions-into-ram (load-instructions :file file))))

(defun main (&key (file nil) (display nil) (stream t) (newline nil))
  (setf *disasm* nil)
  (loop-instructions (load-instructions-into-ram (load-instructions :file file)))
  (when display
    (print-video-ram :stream stream :newline newline)))

Emacs හි ප්‍රතිදානය මෙන්න:

කවුළු දෙකක් සහිත ඉමාක්ස් කවුළුව, වම්පස ලිස්ප් ප්‍රභවයේ කොටසක් සහ දකුණේ අවශ්‍ය අන්තර්ගතය සහිත REPL ප්‍රතිදානය.

මට ප්‍රධාන අංග තුනක් ඉස්මතු කිරීමට අවශ්‍යයි. වැනි උපදෙස්, ක්රියාත්මක කිරීම විට මෙම කේතය මැක්රෝස් බර භාවිතා කරයි mov, xchgසහ artithmetic මෙහෙයුම්. සෑම උපදෙස් සඳහාම disasm-instrසාර්ව ඇමතුමක් ඇතුළත් වේ . මෙය ක්‍රියාත්මක වන වේලාවේදී ගෝලීය විචල්‍ය කට්ටලයක් හරහා සත්‍ය කේතයක් සමඟ විසුරුවා හැරීම ක්‍රියාත්මක කරයි. ලේඛණ සහ වක්‍ර ලිපින සඳහා අගයන් ලිවීම සඳහා භාවිතා කරන ගමනාන්ත-අ nost ෙයවාදී ප්‍රවේශය ගැන මම විශේෂයෙන් ආඩම්බර වෙමි. උපදෙස් ක්‍රියාත්මක කරන මැක්‍රෝස් ගමනාන්තය ගැන තැකීමක් නොකරයි, මන්දයත් එක් එක් හැකියාව සඳහා වෙන් කර ඇති ආකෘති සාමාන්‍යය සමඟ ක්‍රියා කරයිsetf පොදු ලිස්ප් මැක්‍රෝ සමඟ ක්‍රියා කරන බැවිනි.

කේතය මගේ GitHub repo වෙතින් සොයාගත හැකිය . මාස්ටර් හි 8086 හි අනෙකුත් අංග ක්‍රියාත්මක කිරීමට මම දැනටමත් පටන් ගෙන ඇති බැවින් "කෝඩ්ගොල්ෆ්" ශාඛාව සොයා බලන්න. මම දැනටමත් FLAGS ලේඛනය සමඟ පිටාර ගැලීම් සහ සමානාත්මතා ධජ ක්‍රියාත්මක කර ඇත්තෙමි.

නොව 8086 දී මෙම මෙහෙයුම් තුනකින් ඇත 0x82හා 0x83තාර්කික මෙහෙයුම් වන සංස්කරණය. මෙය ඉතා ප්‍රමාද වී ඇති අතර, එම මෙහෙයුම් ඉවත් කිරීම තරමක් අවුල් සහගත වනු ඇත.

මෙම ව්‍යාපාරයේ මුල් අවධියේදී මට ආශ්වාදයක් ලබා දුන් ඔහුගේ පයිතන් අනුවාදය ගැන මම @ja ට ස්තූතිවන්ත වෙමි.


3
ඇදහිය නොහැකි පළමු පිළිතුර! වෙබ් අඩවියට සාදරයෙන් පිළිගනිමු :)
ජේම්ස්

1
ඉතා සිසිල් භාෂා තේරීමක්!
පිටපත් කරන්න

12

සී - 319 කි පේළි 348 ක්

මෙය මගේ තැපැල් පිටපත් වැඩසටහන සී වෙත වැඩි හෝ අඩු සෘජු පරිවර්තනයකි. ඇත්ත වශයෙන්ම තොග භාවිතය පැහැදිලි විචල්‍යයන් මගින් ප්‍රතිස්ථාපනය වේ. උපදෙස් ක්ෂේත්‍රයක් විචල්‍යයන්ට බෙදී ඇත o- උපදෙස් ඔප්කෝඩ් බයිට්, d- දිශා ක්ෂේත්‍රය, w- පළල ක්ෂේත්‍රය. එය "mod-reg-r / m" උපදෙස් නම්, mr-rm බයිට් කියවනු ලැබේ struct rm r. Reg සහ r / m ක්ෂේත්‍ර විකේතනය කිරීම පියවර දෙකකින් ඉදිරියට යයි: දත්ත වෙත දර්ශකය ගණනය කිරීම සහ දත්ත පැටවීම, එකම විචල්‍යය නැවත භාවිතා කිරීම. ඒ නිසා වැනි දෙයක් සඳහාADD AX,BX x , පළමුව x යනු අක්ෂයට දර්ශකයක් වන අතර y යනු bx වෙත දර්ශකයක් වන අතර x යනු අන්තර්ගතය (අක්ෂය) වන අතර y යනු අන්තර්ගතය (bx) වේ. මේ වගේ විවිධ වර්ග සඳහා විචල්‍යය නැවත භාවිතා කිරීම සඳහා වාත්තු ගොඩක් අවශ්‍යයි.

ඔප්කෝඩ් බයිට් ක්‍රියාකාරී ලක්ෂ්‍ය වගුවක් සමඟ විකේතනය කර ඇත. සෑම ක්‍රියාකාරී ශරීරයක්ම නැවත භාවිතා කළ හැකි කොටස් සඳහා මැක්‍රෝස් භාවිතා කරයි. මෙම DWමහා පරිමාණ සියලු opcode කාර්යයන් වත්මන් වන අතර decodes dහා wසිට විචල්ය oopcode බයිට. මෙම RMPසාර්ව කිරිමටද ඇති "mr-rm" බයිට ප්රහේලිකාව ලිහා, සහ පළමු අදියර LDXYදෙවන අදියර සිදු කරයි. ප්‍රති result ලයක් ගබඩා කරන ඔප්කෝඩ් මඟින් pවිචල්‍යය මඟින් ප්‍රති point ල ස්ථානයට දර්ශකය රඳවා තබා ගත හැකි අතර විචල්‍යය ප්‍රති result ල zඅගය රඳවා තබා ගනී. කොඩිය ගණනය කරනු ලබන්නේ zඅගය ගණනය කිරීමෙන් පසුවය . මෙම INCසහ DECමෙහෙයුම් වර්ගීය භාවිතා කිරීමට පෙර ගෙන යෑම ධජය බේරා MATHFLAGSකාර්යය (මෙම කොටසක් ලෙස submacro) සහ රැගෙන යන්න ආරක්ෂා කිරීමට, afterwords එය නැවත.ADD හෝSUB

සංස්කරණය කරන්න: දෝෂ නිවැරදි කර ඇත!
සංස්කරණය කරන්න: පුළුල් කර අදහස් දැක්වීය. විට trace==0වීඩියෝ කුණු කන්ද විට එය දැන් ANSI move-to-0,0 විධානය ප්රතිදානයනට. එබැවින් එය සත්‍ය සංදර්ශකයක් අනුකරණය කිරීම වඩා හොඳය. මෙම BIGENDIAN(පවා නැති බව) දෙයක් ඉවත් කර ඇත. එය සමහර ස්ථානවල කුඩා එන්ඩියන් බයිට් අනුපිළිවෙල මත රඳා පවතී, නමුත් ඊළඟ සංශෝධනයේදී මෙය නිවැරදි කිරීමට මම අදහස් කරමි. මූලික වශයෙන්, සියළුම දර්ශක ප්‍රවේශයන්ට LE අනුපිළිවෙලින් බයිට් පැහැදිලිවම රචනා කරන ( get_සහ) put_කාර්යයන් හරහා යා යුතුය .

#include<ctype.h>
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<unistd.h>
#define P printf
#define R return
#define T typedef
T intptr_t I; T uintptr_t U;
T short S; T unsigned short US;
T signed char C; T unsigned char UC; T void V;  // to make everything shorter
U o,w,d,f; // opcode, width, direction, extra temp variable (was initially for a flag, hence 'f')
U x,y,z;   // left operand, right operand, result
void *p;   // location to receive result
UC halt,debug=0,trace=0,reg[28],null[2],mem[0xffff]={ // operating flags, register memory, RAM
    1, (3<<6),        // ADD ax,ax
    1, (3<<6)+(4<<3), // ADD ax,sp
    3, (3<<6)+(4<<3), // ADD sp,ax
    0xf4 //HLT
};

// register declaration and initialization
#define H(_)_(al)_(ah)_(cl)_(ch)_(dl)_(dh)_(bl)_(bh)
#define X(_)_(ax)     _(cx)     _(dx)     _(bx)     _(sp)_(bp)_(si)_(di)_(ip)_(fl)
#define SS(_)_(cs)_(ds)_(ss)_(es)
#define HD(_)UC*_;      // half-word regs declared as unsigned char *
#define XD(_)US*_;      // full-word regs declared as unsigned short *
#define HR(_)_=(UC*)(reg+i++);      // init and increment by one
#define XR(_)_=(US*)(reg+i);i+=2;   // init and increment by two
H(HD)X(XD)SS(XD)V init(){I i=0;H(HR)i=0;X(XR)SS(XR)}    // declare and initialize register pointers
enum { CF=1<<0, PF=1<<2, AF=1<<4, ZF=1<<6, SF=1<<7, OF=1<<11 };

#define HP(_)P(#_ ":%02x ",*_);     // dump a half-word reg as zero-padded hex
#define XP(_)P(#_ ":%04x ",*_);     // dump a full-word reg as zero-padded hex
V dump(){ //H(HP)P("\n");
    P("\n"); X(XP)
    if(trace)P("%s %s %s %s ",*fl&CF?"CA":"NC",*fl&OF?"OV":"NO",*fl&SF?"SN":"NS",*fl&ZF?"ZR":"NZ");
    P("\n");  // ^^^ crack flag bits into strings ^^^
}

// get and put into memory in a strictly little-endian format
I get_(void*p,U w){R w? *(UC*)p + (((UC*)p)[1]<<8) :*(UC*)p;}
V put_(void*p,U x,U w){ if(w){ *(UC*)p=x; ((UC*)p)[1]=x>>8; }else *(UC*)p=x; }
// get byte or word through ip, incrementing ip
UC fetchb(){ U x = get_(mem+(*ip)++,0); if(trace)P("%02x(%03o) ",x,x); R x; }
US fetchw(){I w=fetchb();R w|(fetchb()<<8);}

T struct rm{U mod,reg,r_m;}rm;      // the three fields of the mod-reg-r/m byte
rm mrm(U m){ R(rm){ (m>>6)&3, (m>>3)&7, m&7 }; }    // crack the mrm byte into fields
U decreg(U reg,U w){    // decode the reg field, yielding a uintptr_t to the register (byte or word)
    if (w)R (U)((US*[]){ax,cx,dx,bx,sp,bp,si,di}[reg]);
    else R (U)((UC*[]){al,cl,dl,bl,ah,ch,dh,bh}[reg]); }
U rs(US*x,US*y){ R get_(x,1)+get_(y,1); }  // fetch and sum two full-words
U decrm(rm r,U w){      // decode the r/m byte, yielding uintptr_t
    U x=(U[]){rs(bx,si),rs(bx,di),rs(bp,si),rs(bp,di),get_(si,1),get_(di,1),get_(bp,1),get_(bx,1)}[r.r_m];
    switch(r.mod){ case 0: if (r.r_m==6) R (U)(mem+fetchw()); break;
                   case 1: x+=fetchb(); break;
                   case 2: x+=fetchw(); break;
                   case 3: R decreg(r.r_m,w); }
    R (U)(mem+x); }

// opcode helpers
    // set d and w from o
#define DW  if(trace){ P("%s:\n",__func__); } \
            d=!!(o&2); \
            w=o&1;
    // fetch mrm byte and decode, setting x and y as pointers to args and p ptr to dest
#define RMP rm r=mrm(fetchb());\
            x=decreg(r.reg,w); \
            y=decrm(r,w); \
            if(trace>1){ P("x:%d\n",x); P("y:%d\n",y); } \
            p=d?(void*)x:(void*)y;

    // fetch x and y values from x and y pointers
#define LDXY \
            x=get_((void*)x,w); \
            y=get_((void*)y,w); \
            if(trace){ P("x:%d\n",x); P("y:%d\n",y); }

    // normal mrm decode and load
#define RM  RMP LDXY

    // immediate to accumulator
#define IA x=(U)(p=w?(UC*)ax:al); \
           x=get_((void*)x,w); \
           y=w?fetchw():fetchb();

    // flags set by logical operators
#define LOGFLAGS  *fl=0; \
                  *fl |= ( (z&(w?0x8000:0x80))           ?SF:0) \
                       | ( (z&(w?0xffff:0xff))==0        ?ZF:0) ;

    // additional flags set by math operators
#define MATHFLAGS *fl |= ( (z&(w?0xffff0000:0xff00))     ?CF:0) \
                       | ( ((z^x)&(z^y)&(w?0x8000:0x80)) ?OF:0) \
                       | ( ((x^y^z)&0x10)                ?AF:0) ;

    // store result to p ptr
#define RESULT \
        if(trace)P(w?"->%04x ":"->%02x ",z); \
        put_(p,z,w);

// operators, composed with helpers in the opcode table below
    // most of these macros will "enter" with x and y already loaded with operands
#define PUSH(x) put_(mem+(*sp-=2),*(x),1)
#define POP(x) *(x)=get_(mem+(*sp+=2)-2,1)
#define ADD z=x+y; LOGFLAGS MATHFLAGS RESULT
#define ADC x+=(*fl&CF); ADD
#define SUB z=d?x-y:y-x; LOGFLAGS MATHFLAGS RESULT
#define SBB d?y+=*fl&CF:(x+=*fl&CF); SUB
#define CMP p=null; SUB
#define AND z=x&y; LOGFLAGS RESULT
#define  OR z=x|y; LOGFLAGS RESULT
#define XOR z=x^y; LOGFLAGS RESULT
#define INC(r) w=1; d=1; p=(V*)r; x=(S)*r; y=1; f=*fl&CF; ADD *fl=(*fl&~CF)|f;
#define DEC(r) w=1; d=1; p=(V*)r; x=(S)*r; y=1; f=*fl&CF; SUB *fl=(*fl&~CF)|f;
#define F(f) !!(*fl&f)
#define J(c) U cf=F(CF),of=F(OF),sf=F(SF),zf=F(ZF); y=(S)(C)fetchb(); \
                  if(trace)P("<%d> ", c); \
                  if(c)*ip+=(S)y;
#define JN(c) J(!(c))
#define IMM(a,b) rm r=mrm(fetchb()); \
            p=(void*)(y=decrm(r,w)); \
            a \
            x=w?fetchw():fetchb(); \
            b \
            d=0; \
            y=get_((void*)y,w); \
            if(trace){ P("x:%d\n",x); P("y:%d\n",y); } \
            if(trace){ P("%s ", (C*[]){"ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"}[r.reg]); } \
            switch(r.reg){case 0:ADD break; \
                          case 1:OR break; \
                          case 2:ADC break; \
                          case 3:SBB break; \
                          case 4:AND break; \
                          case 5:SUB break; \
                          case 6:XOR break; \
                          case 7:CMP break; }
#define IMMIS IMM(w=0;,w=1;x=(S)(C)x;)
#define TEST z=x&y; LOGFLAGS MATHFLAGS
#define XCHG f=x;z=y; LDXY if(w){*(US*)f=y;*(US*)z=x;}else{*(UC*)f=y;*(UC*)z=x;}
#define MOV z=d?y:x; RESULT
#define MOVSEG
#define LEA RMP z=((UC*)y)-mem; RESULT
#define NOP
#define AXCH(r) x=(U)ax; y=(U)(r); w=1; XCHG
#define CBW *ax=(S)(C)*al;
#define CWD z=(I)(S)*ax; *dx=z>>16;
#define CALL x=w?fetchw():(S)(C)fetchb(); PUSH(ip); (*ip)+=(S)x;
#define WAIT
#define PUSHF PUSH(fl)
#define POPF POP(fl)
#define SAHF x=*fl; y=*ah; x=(x&~0xff)|y; *fl=x;
#define LAHF *ah=(UC)*fl;
#define mMOV if(d){ x=get_(mem+fetchw(),w); if(w)*ax=x; else*al=x; } \
             else { put_(mem+fetchw(),w?*ax:*al,w); }
#define MOVS
#define CMPS
#define STOS
#define LODS
#define SCAS
#define iMOVb(r) (*r)=fetchb();
#define iMOVw(r) (*r)=fetchw();
#define RET(v) POP(ip); if(v)*sp+=v*2;
#define LES
#define LDS
#define iMOVm if(w){iMOVw((US*)y)}else{iMOVb((UC*)y)}
#define fRET(v) POP(cs); RET(v)
#define INT(v)
#define INT0
#define IRET
#define Shift rm r=mrm(fetchb());
#define AAM
#define AAD
#define XLAT
#define ESC(v)
#define LOOPNZ
#define LOOPZ
#define LOOP
#define JCXZ
#define IN
#define OUT
#define INv
#define OUTv
#define JMP x=fetchw(); *ip+=(S)x;
#define sJMP x=(S)(C)fetchb(); *ip+=(S)x;
#define FARJMP
#define LOCK
#define REP
#define REPZ
#define HLT halt=1
#define CMC *fl=(*fl&~CF)|((*fl&CF)^1);
#define NOT
#define NEG
#define MUL
#define IMUL
#define DIV
#define IDIV
#define Grp1 rm r=mrm(fetchb()); \
             y=decrm(r,w); \
             if(trace)P("%s ", (C*[]){}[r.reg]); \
             switch(r.reg){case 0: TEST; break; \
                           case 2: NOT; break; \
                           case 3: NEG; break; \
                           case 4: MUL; break; \
                           case 5: IMUL; break; \
                           case 6: DIV; break; \
                           case 7: IDIV; break; }
#define Grp2 rm r=mrm(fetchb()); \
             y=decrm(r,w); \
             if(trace)P("%s ", (C*[]){"INC","DEC","CALL","CALL","JMP","JMP","PUSH"}[r.reg]); \
             switch(r.reg){case 0: INC((S*)y); break; \
                           case 1: DEC((S*)y); break; \
                           case 2: CALL; break; \
                           case 3: CALL; break; \
                           case 4: *ip+=(S)y; break; \
                           case 5: JMP; break; \
                           case 6: PUSH((S*)y); break; }
#define CLC *fl=*fl&~CF;
#define STC *fl=*fl|CF;
#define CLI
#define STI
#define CLD
#define STD

// opcode table
// An x-macro table of pairs (a, b) where a becomes the name of a void function(void) which
// implements the opcode, and b comprises the body of the function (via further macro expansion)
#define OP(_)\
/*dw:bf                 wf                     bt                    wt   */ \
_(addbf, RM ADD)      _(addwf, RM ADD)       _(addbt,  RM ADD)     _(addwt, RM ADD)     /*00-03*/\
_(addbi, IA ADD)      _(addwi, IA ADD)       _(pushes, PUSH(es))   _(popes, POP(es))    /*04-07*/\
_(orbf,  RM OR)       _(orwf,  RM OR)        _(orbt,   RM OR)      _(orwt,  RM OR)      /*08-0b*/\
_(orbi,  IA OR)       _(orwi,  IA OR)        _(pushcs, PUSH(cs))   _(nop0,       )      /*0c-0f*/\
_(adcbf, RM ADC)      _(adcwf, RM ADC)       _(adcbt,  RM ADC)     _(adcwt, RM ADC)     /*10-13*/\
_(adcbi, IA ADC)      _(adcwi, IA ADC)       _(pushss, PUSH(ss))   _(popss, POP(ss))    /*14-17*/\
_(sbbbf, RM SBB)      _(sbbwf, RM SBB)       _(sbbbt,  RM SBB)     _(sbbwt, RM SBB)     /*18-1b*/\
_(sbbbi, IA SBB)      _(sbbwi, IA SBB)       _(pushds, PUSH(ds))   _(popds, POP(ds))    /*1c-1f*/\
_(andbf, RM AND)      _(andwf, RM AND)       _(andbt, RM AND)      _(andwt, RM AND)     /*20-23*/\
_(andbi, IA AND)      _(andwi, IA AND)       _(esseg, )            _(daa, )             /*24-27*/\
_(subbf, RM SUB)      _(subwf, RM SUB)       _(subbt, RM SUB)      _(subwt, RM SUB)     /*28-2b*/\
_(subbi, IA SUB)      _(subwi, IA SUB)       _(csseg, )            _(das, )             /*2c-2f*/\
_(xorbf, RM XOR)      _(xorwf, RM XOR)       _(xorbt, RM XOR)      _(xorwt, RM XOR)     /*30-33*/\
_(xorbi, IA XOR)      _(xorwi, IA XOR)       _(ssseg, )            _(aaa, )             /*34-37*/\
_(cmpbf, RM CMP)      _(cmpwf, RM CMP)       _(cmpbt, RM CMP)      _(cmpwt, RM CMP)     /*38-3b*/\
_(cmpbi, IA CMP)      _(cmpwi, IA CMP)       _(dsseg, )            _(aas, )             /*3c-3f*/\
_(incax, INC(ax))     _(inccx, INC(cx))      _(incdx, INC(dx))     _(incbx, INC(bx))    /*40-43*/\
_(incsp, INC(sp))     _(incbp, INC(bp))      _(incsi, INC(si))     _(incdi, INC(di))    /*44-47*/\
_(decax, DEC(ax))     _(deccx, DEC(cx))      _(decdx, DEC(dx))     _(decbx, DEC(bx))    /*48-4b*/\
_(decsp, DEC(sp))     _(decbp, DEC(bp))      _(decsi, DEC(si))     _(decdi, DEC(di))    /*4c-4f*/\
_(pushax, PUSH(ax))   _(pushcx, PUSH(cx))    _(pushdx, PUSH(dx))   _(pushbx, PUSH(bx))  /*50-53*/\
_(pushsp, PUSH(sp))   _(pushbp, PUSH(bp))    _(pushsi, PUSH(si))   _(pushdi, PUSH(di))  /*54-57*/\
_(popax, POP(ax))     _(popcx, POP(cx))      _(popdx, POP(dx))     _(popbx, POP(bx))    /*58-5b*/\
_(popsp, POP(sp))     _(popbp, POP(bp))      _(popsi, POP(si))     _(popdi, POP(di))    /*5c-5f*/\
_(nop1, ) _(nop2, )   _(nop3, ) _(nop4, )    _(nop5, ) _(nop6, )   _(nop7, ) _(nop8, )  /*60-67*/\
_(nop9, ) _(nopA, )   _(nopB, ) _(nopC, )    _(nopD, ) _(nopE, )   _(nopF, ) _(nopG, )  /*68-6f*/\
_(jo, J(of))          _(jno, JN(of))         _(jb, J(cf))          _(jnb, JN(cf))       /*70-73*/\
_(jz, J(zf))          _(jnz, JN(zf))         _(jbe, J(cf|zf))      _(jnbe, JN(cf|zf))   /*74-77*/\
_(js, J(sf))          _(jns, JN(sf))         _(jp, )               _(jnp, )             /*78-7b*/\
_(jl, J(sf^of))       _(jnl_, JN(sf^of))     _(jle, J((sf^of)|zf)) _(jnle,JN((sf^of)|zf))/*7c-7f*/\
_(immb, IMM(,))       _(immw, IMM(,))        _(immb1, IMM(,))      _(immis, IMMIS)      /*80-83*/\
_(testb, RM TEST)     _(testw, RM TEST)      _(xchgb, RMP XCHG)    _(xchgw, RMP XCHG)   /*84-87*/\
_(movbf, RM MOV)      _(movwf, RM MOV)       _(movbt, RM MOV)      _(movwt, RM MOV)     /*88-8b*/\
_(movsegf, RM MOVSEG) _(lea, LEA)            _(movsegt, RM MOVSEG) _(poprm,RM POP((US*)p))/*8c-8f*/\
_(nopH, )             _(xchgac, AXCH(cx))    _(xchgad, AXCH(dx))   _(xchgab, AXCH(bx))  /*90-93*/\
_(xchgasp, AXCH(sp))  _(xchabp, AXCH(bp))    _(xchgasi, AXCH(si))  _(xchadi, AXCH(di))  /*94-97*/\
_(cbw, CBW)           _(cwd, CWD)            _(farcall, )          _(wait, WAIT)        /*98-9b*/\
_(pushf, PUSHF)       _(popf, POPF)          _(sahf, SAHF)         _(lahf, LAHF)        /*9c-9f*/\
_(movalb, mMOV)       _(movaxw, mMOV)        _(movbal, mMOV)       _(movwax, mMOV)      /*a0-a3*/\
_(movsb, MOVS)        _(movsw, MOVS)         _(cmpsb, CMPS)        _(cmpsw, CMPS)       /*a4-a7*/\
_(testaib, IA TEST)   _(testaiw, IA TEST)    _(stosb, STOS)        _(stosw, STOS)       /*a8-ab*/\
_(lodsb, LODS)        _(lodsw, LODS)         _(scasb, SCAS)        _(scasw, SCAS)       /*ac-af*/\
_(movali, iMOVb(al))  _(movcli, iMOVb(cl))   _(movdli, iMOVb(dl))  _(movbli, iMOVb(bl)) /*b0-b3*/\
_(movahi, iMOVb(ah))  _(movchi, iMOVb(ch))   _(movdhi, iMOVb(dh))  _(movbhi, iMOVb(bh)) /*b4-b7*/\
_(movaxi, iMOVw(ax))  _(movcxi, iMOVw(cx))   _(movdxi, iMOVw(dx))  _(movbxi, iMOVw(bx)) /*b8-bb*/\
_(movspi, iMOVw(sp))  _(movbpi, iMOVw(bp))   _(movsii, iMOVw(si))  _(movdii, iMOVw(di)) /*bc-bf*/\
_(nopI, )             _(nopJ, )              _(reti, RET(fetchw())) _(retz, RET(0))     /*c0-c3*/\
_(les, LES)           _(lds, LDS)            _(movimb, RMP iMOVm)  _(movimw, RMP iMOVm) /*c4-c7*/\
_(nopK, )             _(nopL, )              _(freti, fRET(fetchw())) _(fretz, fRET(0)) /*c8-cb*/\
_(int3, INT(3))       _(inti, INT(fetchb())) _(int0, INT(0))       _(iret, IRET)        /*cc-cf*/\
_(shiftb, Shift)      _(shiftw, Shift)       _(shiftbv, Shift)     _(shiftwv, Shift)    /*d0-d3*/\
_(aam, AAM)           _(aad, AAD)            _(nopM, )             _(xlat, XLAT)        /*d4-d7*/\
_(esc0, ESC(0))       _(esc1, ESC(1))        _(esc2, ESC(2))       _(esc3, ESC(3))      /*d8-db*/\
_(esc4, ESC(4))       _(esc5, ESC(5))        _(esc6, ESC(6))       _(esc7, ESC(7))      /*dc-df*/\
_(loopnz, LOOPNZ)     _(loopz, LOOPZ)        _(loop, LOOP)         _(jcxz, JCXZ)        /*e0-e3*/\
_(inb, IN)            _(inw, IN)             _(outb, OUT)          _(outw, OUT)         /*e4-e7*/\
_(call, w=1; CALL)    _(jmp, JMP)            _(farjmp, FARJMP)     _(sjmp, sJMP)        /*e8-eb*/\
_(invb, INv)          _(invw, INv)           _(outvb, OUTv)        _(outvw, OUTv)       /*ec-ef*/\
_(lock, LOCK)         _(nopN, )              _(rep, REP)           _(repz, REPZ)        /*f0-f3*/\
_(hlt, HLT)           _(cmc, CMC)            _(grp1b, Grp1)        _(grp1w, Grp1)       /*f4-f7*/\
_(clc, CLC)           _(stc, STC)            _(cli, CLI)           _(sti, STI)          /*f8-fb*/\
_(cld, CLD)           _(std, STD)            _(grp2b, Grp2)        _(grp2w, Grp2)       /*fc-ff*/
#define OPF(a,b)void a(){DW b;}     // generate opcode function
#define OPN(a,b)a,                  // extract name
OP(OPF)void(*tab[])()={OP(OPN)};    // generate functions, declare and populate fp table with names

V clean(C*s){I i;       // replace unprintable characters in 80-byte buffer with spaces
    for(i=0;i<80;i++)
        if(!isprint(s[i]))
            s[i]=' ';
}
V video(){I i;          // dump the (cleaned) video memory to the console
    C buf[81]="";
    if(!trace)P("\e[0;0;f");
    for(i=0;i<28;i++)
        memcpy(buf, mem+0x8000+i*80, 80),
        clean(buf),
        P("\n%s",buf);
    P("\n");
}

static I ct;        // timer memory for period video dump
V run(){while(!halt){if(trace)dump();
    if(!ct--){ct=10; video();}
    tab[o=fetchb()]();}}
V dbg(){
    while(!halt){
        C c;
        if(!ct--){ct=10; video();}
        if(trace)dump();
        //scanf("%c", &c);
        fgetc(stdin);
        //switch(c){
        //case '\n':
        //case 's':
            tab[o=fetchb()]();
            //break;
        //}
    }
}

I load(C*f){struct stat s; FILE*fp;     // load a file into memory at address zero
    R (fp=fopen(f,"rb"))
        && fstat(fileno(fp),&s) || fread(mem,s.st_size,1,fp); }

I main(I c,C**v){
    init();
    if(c>1){            // if there's an argument
        load(v[1]);     //     load named file
    }
    *sp=0x100;          // initialize stack pointer
    if(debug) dbg();    // if debugging, debug
    else run();         // otherwise, just run
    video();            // dump final video
    R 0;}               // remember what R means? cf. line 9

විවිධ මෙහෙයුම් වල අදියර සඳහා මැක්‍රෝස් භාවිතා කිරීම, පෝස්ට් ස්ක්‍රිප්ට් කේතය තනිකරම අනුක්‍රමික ආකාරයකින් ක්‍රියාත්මක වන ආකාරයට ඉතා සමීප අර්ථකථන ගැලපීමක් ඇති කරයි. උදාහරණයක් ලෙස, පළමු ඔප්කෝඩ් හතර වන 0x00-0x03 යනු විවිධ දිශාවන් (REG -> REG / MOD, REG <- REG / MOD) සහ බයිට් / වචන ප්‍රමාණයන් සහිත ADD උපදෙස් වේ, එබැවින් ඒවා ක්‍රියාකාරී වගුවේ හරියටම සමාන වේ .

_(addbf, RM ADD)      _(addwf, RM ADD)       _(addbt,  RM ADD)     _(addwt, RM ADD)

මෙම සාර්ව සමඟ ක්‍රියාකාරී වගුව ක්ෂණිකව සකසා ඇත:

OP(OPF)

එය OPF()එක් එක් ඔප්කෝඩ් නිරූපණයට අදාළ වේ . OPF()ලෙස අර්ථ දැක්වෙන්නේ:

#define OPF(a,b)void a(){DW b;}     // generate opcode function

ඉතින්, පළමු ඔප්කෝඩ් හතර (එක් වරක්) දක්වා පුළුල් වේ:

void addbf(){ DW RM ADD ; }
void addwf(){ DW RM ADD ; }
void addbt(){ DW RM ADD ; }
void addwt(){ DW RM ADD ; }

මෙම කාර්යයන් DWඔප්කෝඩ් බයිට් වලින් කෙළින්ම දිශාව සහ බයිට් / වචන බිටු තීරණය කරන සාර්වයේ ප්‍රති result ලයෙන් වෙන්කර හඳුනා ගනී . මෙම එක් ශ්‍රිතයක ශරීරය පුළුල් කිරීම (වරක්) නිපදවයි:

if(trace){ P("%s:\n",__func__); }  // DW: set d and w from o
d=!!(o&2);
w=o&1;
RMP LDXY  // RM: normal mrm decode and load
z=x+y; LOGFLAGS MATHFLAGS RESULT  // ADD
;

ප්‍රධාන ලූපය දැනටමත් oවිචල්‍යය සකසා ඇති තැන :

while(!halt){tab[o=fetchb()]();}}

තවත් එක් වරක් පුළුල් කිරීමෙන් ඔප්කෝඩයේ සියලුම “මස්” ලබා දෙයි:

// DW: set d and w from o
if(trace){ P("%s:\n",__func__); }
d=!!(o&2);
w=o&1;

// RMP: fetch mrm byte and decode, setting x and y as pointers to args and p ptr to dest
rm r=mrm(fetchb());
x=decreg(r.reg,w);
y=decrm(r,w);
if(trace>1){ P("x:%d\n",x); P("y:%d\n",y); }
p=d?(void*)x:(void*)y;

// LDXY: fetch x and y values from x and y pointers
x=get_((void*)x,w);
y=get_((void*)y,w);
if(trace){ P("x:%d\n",x); P("y:%d\n",y); }

z=x+y;   // ADD
// LOGFLAGS: flags set by logical operators
*fl=0;
*fl |= ( (z&(w?0x8000:0x80))           ?SF:0)
     | ( (z&(w?0xffff:0xff))==0        ?ZF:0) ;

// MATHFLAGS: additional flags set by math operators
*fl |= ( (z&(w?0xffff0000:0xff00))     ?CF:0)
     | ( ((z^x)&(z^y)&(w?0x8000:0x80)) ?OF:0)
     | ( ((x^y^z)&0x10)                ?AF:0) ;

// RESULT: store result to p ptr
if(trace)P(w?"->%04x ":"->%02x ",z);
put_(p,z,w);
;

මගින් සම්මත සහ පූර්ණ-preprocessed කාර්යය, indent:

void
addbf ()
{
  if (trace)
    {
      printf ("%s:\n", __func__);
    }
  d = ! !(o & 2);
  w = o & 1;
  rm r = mrm (fetchb ());
  x = decreg (r.reg, w);
  y = decrm (r, w);
  if (trace > 1)
    {
      printf ("x:%d\n", x);
      printf ("y:%d\n", y);
    }
  p = d ? (void *) x : (void *) y;
  x = get_ ((void *) x, w);
  y = get_ ((void *) y, w);
  if (trace)
    {
      printf ("x:%d\n", x);
      printf ("y:%d\n", y);
    }
  z = x + y;
  *fl = 0;
  *fl |=
    ((z & (w ? 0x8000 : 0x80)) ? SF : 0) | ((z & (w ? 0xffff : 0xff)) ==
                        0 ? ZF : 0);
  *fl |=
    ((z & (w ? 0xffff0000 : 0xff00)) ? CF : 0) |
    (((z ^ x) & (z ^ y) & (w ? 0x8000 : 0x80)) ? OF : 0) |
    (((x ^ y ^ z) & 0x10) ? AF : 0);
  if (trace)
    printf (w ? "->%04x " : "->%02x ", z);
  put_ (p, z, w);;
}

එදිනෙදා භාවිතය සඳහා ශ්‍රේෂ් greatest තම සී විලාසිතාව නොවේ, නමුත් මේ ආකාරයෙන් මැක්‍රෝස් භාවිතා කිරීම මෙහි ක්‍රියාත්මක කිරීම ඉතා කෙටි හා ඉතා සෘජු කිරීම සඳහා පරිපූර්ණ බව පෙනේ.

හෝඩුවාවේ ප්‍රතිදානයේ වලිගය සහිත පරීක්ෂණ වැඩසටහන් ප්‍රතිදානය:

43(103) incbx:
->0065 
ax:0020 cx:0015 dx:0190 bx:0065 sp:1000 bp:0000 si:0000 di:00c2 ip:013e fl:0000 NC NO NS NZ 
83(203) immis:
fb(373) 64(144) x:100
y:101
CMP ->0001 
ax:0020 cx:0015 dx:0190 bx:0065 sp:1000 bp:0000 si:0000 di:00c2 ip:0141 fl:0000 NC NO NS NZ 
76(166) jbe:
da(332) <0> 
ax:0020 cx:0015 dx:0190 bx:0065 sp:1000 bp:0000 si:0000 di:00c2 ip:0143 fl:0000 NC NO NS NZ 
f4(364) hlt:

.........                                                                       
Hello, world!                                                                   
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 


################################################################################
##                                                                            ##
##  0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987                          ##
##                                                                            ##
##  0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400     ##
##                                                                            ##
##  2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97    ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
##                                                                            ##
################################################################################

මම comp.lang.c හි පෙර සංස්කරණ කිහිපයක් බෙදා ගත්තද ඒවා එතරම් උනන්දුවක් දැක්වූයේ නැත.




3

පැස්කල් - සුදු පැහැ ගැන්වීම්, අදහස් දැක්වීම් සහ නිදොස් කිරීමේ ක්‍රියාකාරකම් ඇතුළුව පේළි 667 ක්.

ප්‍රමාද ඉදිරිපත් කිරීමක් ... නමුත් පැස්කල් වෙත තවමත් ප්‍රවේශයක් නොතිබූ බැවින් ...
එය තවම අවසන් නැති නමුත් එය ක්‍රියාත්මක වේ. සුදු රේඛා, අදහස් සහ නිදොස් කිරීමේ පුරුදු ඉවත් කිරීමෙන් බොහෝ කෙටි විය හැකිය.
නමුත් අනෙක් අතට ... කේතය කියවිය හැකි විය යුතුය (මම පැස්කල් පරිශීලකයෙකු වීමට හේතුව එයයි)

පර්යන්ත දර්ශනය

(******************************************************************************
*  emulator for 8086/8088 subset as requested in                              *
* /codegolf/4732/emulate-an-intel-8086-cpu *
* (c)2019 by ir. Marc Dendooven                                               *
* V0.2 DEV                                                                    *
******************************************************************************) 

program ed8086;
uses sysutils;

const showSub = 0; // change level to show debug info

type    nibble = 0..15;
        oct = 0..7;
        quad = 0..3;
        address = 0..$FFFF; // should be extended when using segmentation

const memSize = $9000; 
      AX=0; CX=1; DX=2; BX=3; SP=4; BP=5; SI=6; DI=7;

type location = record
                    memory: boolean; // memory or register
                    aORi: address; // address or index to register
                    content: word
                end;

var mem: array[0..memSize-1] of byte;
    IP,segEnd: word;
    IR: byte;
    mode: quad;
    sreg: oct;
    rm: oct;
    RX: array[AX..DI] of word; //AX,CX,DX,BX,SP,BP,SI,DI
    FC,FZ,FS: 0..1;
    cnt: cardinal = 0;
    d: 0..1;
    oper1,oper2: location;
    w: boolean; // is true when word / memory
    calldept: cardinal = 0;
    T: Dword;

// ---------------- general help methods ----------------
procedure display;
var x,y: smallint;
    c: byte;
begin
    writeln;
    for y := 0 to 24 do
        begin
          for x := 0 to 79 do
            begin
                c := mem[$8000+y*80+x];
                if c=0 then write(' ') else write(char(c));
            end;
            writeln
        end
end;    

procedure error(s: string);
begin
    writeln;writeln;
    writeln('ERROR: ',s);
    writeln('program aborted');
    writeln;
    writeln('IP=',hexstr(IP,4),' IR=',hexstr(IR,2));
    display;
    halt
end;

procedure debug(s: string);
begin
    if CallDept < showSub then writeln(s)
end;

procedure load;
// load the codegolf binary at address 0
var f,count: LongInt;
begin
    if not fileExists('codegolf') then error('file "codegolf" doesn''t exist in this directory');
    f := fileOpen('codegolf',fmOpenRead);
    count := fileRead(f,mem,memSize);
    fileClose(f);
    if count = -1 then error('Could not read file "codegolf"');
    writeln(count, ' bytes read to memory starting at 0');
    segEnd := count;
    writeln
end;

procedure mon;
begin
    if not (CallDept < showSub) then exit;
    writeln;
    writeln('------------- mon -------------');
    writeln('IP=',hexstr(IP,4));
    writeln('AX=',hexstr(RX[AX],4),' CX=',hexstr(RX[CX],4),' DX=',hexstr(RX[DX],4),' BX=',hexstr(RX[BX],4));
    writeln('SP=',hexstr(RX[SP],4),' BP=',hexstr(RX[BP],4),' SI=',hexstr(RX[SI],4),' DI=',hexstr(RX[DI],4));
    writeln('C=',FC,' Z=',FZ,' S=',FS);
    writeln('-------------------------------');
    writeln
end;

// --------------- memory and register access ----------------
// memory should NEVER be accessed direct
// in order to intercept memory mapped IO

function peek(a:address):byte;
begin
    peek := mem[a]
end;

procedure poke(a:address;b:byte);
begin
    mem[a]:=b;
    if not (CallDept < showSub) then exit;
    case a of $8000..$87CF: 
        begin 
            writeln;
            writeln('*** a character has been written to the screen ! ***');
            writeln('''',chr(b),''' to screenpos ',a-$8000)
        end
    end
end;

function peek2(a:address):word;
begin
    peek2 := peek(a)+peek(a+1)*256 
end;

procedure poke2(a:address; b:word);
begin
    poke(a,lo(b));
    poke(a+1,hi(b))
end;

function peekX(a: address): word;
begin
    if w then peekX := peek2(a) else peekX := peek(a)
end;

function fetch: byte;
begin
    fetch := peek(IP); inc(IP);
    debug('----fetching '+hexStr(fetch,2))
end;

function fetch2: word;
begin
    fetch2 := peek2(IP); inc(IP,2);
    debug('----fetching '+hexStr(fetch2,4))
end;

function getReg(r: oct): byte;
begin
    if r<4 then getReg := lo(RX[r])
            else getreg := hi(RX[r-4])
end;

function getReg2(r: oct): word;
begin
    getreg2 := RX[r]
end;

function getRegX(r: oct): word;
begin
    if w then getregX := getReg2(r) else getRegX := getReg(r)
end;

procedure test_ZS;
begin
    if w then FZ:=ord(oper1.content=0)
         else FZ:=ord(lo(oper1.content)=0);
    if w then FS:=ord(oper1.content>=$8000)
         else FS:=ord(oper1.content>=$80)
end;

procedure test_CZS;
begin
    test_ZS;
    if w then FC := ord(T>$FFFF)
         else FC := ord(T>$FF);
end;

// -------------- memory mode methods ------------------

procedure modRM;
// reads MRM byte
// sets mode (=the way rm is exploited)
// sets sreg: select general register (in G memory mode) or segment register
// sets rm: select general register or memory (in E memory mode)
var MrM: byte;
begin
    debug('---executing modRm');
    MrM := fetch;
    mode := MrM >> 6;
    sreg := (MrM and %00111000) >> 3;
    rm := MrM and %00000111;
    debug('------modRm '+hexstr(MrM,2)+' '+binstr(MrM,8)+'  '+
            'mode='+hexStr(mode,1)+' sreg='+hexStr(sreg,1)+' rm='+hexStr(rm,1))
end;


function mm_G: location;
// The reg field of the ModR/M byte selects a general register.
var oper: location;
begin
    debug('---executing mm_G');
    debug ('*** warning *** check for byte/word operations');   
    oper.memory := false;
    oper.aORi := sreg;
    oper.content := getRegX(sreg);
    debug('------register '+hexStr(sreg,1)+' read');
    mm_G := oper
end;

function mm_E: location;
// A ModR/M byte follows the opcode and specifies the operand. The operand is either a general­
// purpose register or a memory address. If it is a memory address, the address is computed from a
// segment register and any of the following values: a base register, an index register, a displacement.
var oper: location;
begin
    debug('---executing mm_E');
    case mode of
    0:  begin
            oper.memory := true;
            case rm of
            1: begin
                    oper.aORi:= RX[BX]+RX[DI];
                    oper.content := peekX(oper.aORi);
               end;
            6: begin //direct addressing
                    oper.aORi := fetch2;
                    oper.content := peekX(oper.aORi);
                    debug('----------direct addressing');
                    debug('----------address='+hexstr(oper.aORi,4));
                    debug('----------value='+hexStr(oper.content,4))
               end;
            7: begin
                    oper.aORi := RX[BX];
                    oper.content := peekX(oper.aORi)
               end;
            else
                error('mode=0, rm value not yet implemented')
            end
        end;
//  1: + 8 bit signed displacement      
    2:  begin
            oper.memory := true;
            case rm of
            5:  begin
                    oper.aORi := RX[DI]+fetch2; //16 unsigned displacement
                    oper.content := peekX(oper.aORi)
                end;
            7:  begin
                    oper.aORi := RX[BX]+fetch2; //16 unsigned displacement
                    oper.content := peekX(oper.aORi)
                end
            else
                error('mode=2, rm value not yet implemented')
            end
        end;
    3:  begin
            oper.memory := false;
            oper.aORi := rm;
            oper.content := getRegX(rm);
            debug('------register '+hexStr(rm,1)+' read');
        end;
    else
        error('mode '+intToStr(mode)+' of Ew not yet implemented')
    end;
    mm_E := oper
end;

function mm_I: location;
begin
    debug('---executing mm_I');
    if w
        then if d=0     then mm_I.content := fetch2
                        else mm_I.content := int8(fetch)
        else mm_I.content := fetch;
    debug('------imm val read is '+hexStr(mm_I.content,4))
end;

procedure mm_EI;
// E should be called before I since immediate data comes last
begin
    modRM;
    oper1 := mm_E;
    oper2 := mm_I;
end;

procedure mm_EG;
begin
    modRM;
    if d=0  then begin oper1 := mm_E; oper2 := mm_G end
            else begin oper1 := mm_G; oper2 := mm_E end;
end;

procedure mm_AI;
begin
    oper1.memory := false;
    oper1.aORi := 0;
    oper1.content := getRegX(0);
    debug('----------address='+hexstr(oper1.aORi,4));
    debug('----------value='+hexStr(oper1.content,4));
    oper2 := mm_I
end;

procedure writeback;
begin
    with oper1 do
     begin
        debug('--executing writeBack');
        debug(hexStr(ord(memory),1));
        debug(hexStr(aORi,4));
        debug(hexStr(content,4));       
        if w 
            then
                if memory   then poke2(aORi,content)
                            else RX[aORi]:=content
            else
                if memory   then poke(aORi,content)
                            else 
                                if aORi<4   then RX[aORi] := hi(RX[aORi])*256+content
                                            else RX[aORi-4] := content*256+lo(RX[aORi-4])
     end            
end;

// -------------------------- instructions -------------------

procedure i_Jcond;
// fetch next byte
// if condition ok then add to IP as two's complement
var b: byte;
    cc: 0..$F;
begin
    debug('--executing Jcond');
    b := fetch;
    cc := IR and %1111;
    case cc of
        2:if FC=1 then IP := IP + int8(b); //JB, JC
        4:if FZ=1 then IP := IP + int8(b); //JZ
        5:if FZ=0 then IP := IP + int8(b); //JNZ
        6:if (FC=1) or (FZ=1) then IP := IP + int8(b); //JBE
        7:if (FC=0) and (FZ=0) then IP := IP + int8(b); // JA, JNBE
        9:if FS=0 then IP := IP + int8(b); //JNS
        else error('JCond not implemented for condition '+hexstr(cc,1))
    end 
end;

procedure i_HLT;
begin
    debug('--executing HLT');
    writeln;writeln('*** program terminated by HLT instruction ***');
    writeln('--- In the ''codegolf'' program this probably means');
    writeln('--- there is some logical error in the emulator');
    writeln('--- or the program reached the end without error');
    writeln('bye');
    display;
    halt
end;

procedure i_MOV;
begin
    debug('--executing MOV EG');
    debug('------'+hexStr(oper1.aORi,4)+' '+hexStr(oper1.content,4));
    debug('------'+hexStr(oper2.aORi,4)+' '+hexStr(oper2.content,4));
    oper1.content := oper2.content; 
    debug('------'+hexStr(oper1.aORi,4)+' '+hexStr(oper1.content,4));
    writeBack
end;

procedure i_XCHG;
var T: word; 
begin
        debug('--executing XCHG EG');
        T := oper1.content;
        oper1.content := oper2.content;
        oper2.content := T;
        writeback;
        oper1 := oper2;
        writeback
end;

procedure i_XCHG_RX_AX;
var T: word;
begin
    debug('--executing XCHG RX AX');
    T := RX[AX];
    RX[AX] := RX[IR and %111];
    RX[IR and %111] := T
end;

procedure i_MOV_RX_Iw;
begin 
    debug('--executing MOV Rw ,Iw');
    RX[IR and %111] := fetch2 
end;

procedure i_MOV_R8_Ib;
var r: oct;
    b: byte;
begin
    debug('--executing MOV Rb ,Ib');
    b := fetch;
    r := IR and %111;
    if r<4  then RX[r] := hi(RX[r])*256+b
            else RX[r-4] := b*256+lo(RX[r-4]) 
end;

procedure i_PUSH_RX;
begin
    debug('--executing PUSH RX');
    dec(RX[SP],2); //SP:=SP-2
    poke2(RX[SP],RX[IR and %111]) //poke(SP,RX) 
end;

procedure i_POP_RX;
begin
    debug('--executing POP RX');
    RX[IR and %111] := peek2(RX[SP]); //RX := peek(SP)
    inc(RX[SP],2); //SP:=SP+2
end;

procedure i_JMP_Jb;
var b: byte;
begin
    debug('--executing JMP Jb');    
    b := fetch;
    IP:=IP+int8(b)
end;

procedure i_CALL_Jv;
var w: word;
begin
    debug('--executing CALL Jv');   
    w := fetch2;
    dec(RX[SP],2); //SP:=SP-2   
    poke2(RX[SP],IP);
    IP:=IP+int16(w);
    inc(calldept)
end;

procedure i_RET;
begin
    debug('--executing RET');
    IP := peek2(RX[SP]);
    inc(RX[SP],2); //SP:=SP+2
    dec(calldept)
end;

procedure i_XOR;
begin
    debug('--executing XOR');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));    
    oper1.content:=oper1.content xor oper2.content;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_ZS;
    FC:=0;
    writeback
end;

procedure i_OR;
begin
    debug('--executing OR');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));    
    oper1.content:=oper1.content or oper2.content;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_ZS;
    FC:=0;
    writeback
end;

procedure i_AND;
begin
    debug('--executing AND');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));    
    oper1.content:=oper1.content and oper2.content;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_ZS;
    FC:=0;
    writeback
end;

procedure i_ADD;
begin
    debug('--executing ADD');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    T := oper1.content + oper2.content;
    oper1.content := T;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_CZS;
    writeback
end;

procedure i_ADC;
begin
    debug('--executing ADC');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    T := oper1.content + oper2.content + FC;
    oper1.content := T;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_CZS;
    writeback
end;

procedure i_SUB;
begin
    debug('--executing SUB');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    T := oper1.content - oper2.content;
    oper1.content := T;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_CZS;
    writeback
end;

procedure i_SBB;
begin
    debug('--executing SBB');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    T := oper1.content - oper2.content - FC;
    oper1.content := T;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_CZS;
    writeback
end;

procedure i_CMP;
begin
    debug('--executing CMP');
    T:=oper1.content-oper2.content;
    oper1.content:=T;
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_CZS;
end;

procedure i_INC;
begin
    debug('--executing INC');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    inc(oper1.content);
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_ZS;
    // FC unchanged
    writeback
end;

procedure i_DEC;
begin
    debug('--executing DEC');
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    dec(oper1.content);
    debug('------'+hexStr(oper1.content,4)+' '+hexStr(oper2.content,4));
    test_ZS;
    // FC unchanged
    writeback
end;

procedure i_INC_RX;
var r: oct;
begin
    debug('--executing INC RX');
    r := IR and %111;
    inc(RX[r]);
    FZ:=ord(RX[r]=0);
    FS:=ord(RX[r]>=$8000)
    // FC unchanged
end;

procedure i_DEC_RX;
var r: oct;
begin
    debug('--executing DEC RX');
    r := IR and %111;
    dec(RX[r]);
    FZ:=ord(RX[r]=0);
    FS:=ord(RX[r]>=$8000)
    // FC unchanged
end;
// ------------------ special instructions --------------

procedure GRP1;
// GRP1 instructions use modRM byte
// sreg selects instruction
// one operand selected by rm in mm_E
// other operand is Immediate:
begin
    debug('-executing GRP1');
    case sreg of
    0:i_ADD;
    1:i_OR;
    2:i_ADC;
    4:i_AND;
    5:i_SUB;
    7:i_CMP;
    else
        error('subInstruction GRP1 number '+intToStr(sreg)+' is not yet implemented')
    end
end;

procedure GRP4;
begin
    debug('-executing GRP4 Eb');
    modRM;
    oper1 := mm_E;
    case sreg of
    0:i_INC;
    1:i_DEC;
    else
        error('subInstruction GRP4 number '+intToStr(sreg)+' is not yet implemented')
    end
end;

begin //main
    writeln('+-----------------------------------------------+');
    writeln('| emulator for 8086/8088 subset as requested in |');
    writeln('| codegolf challenge                            |');
    writeln('| (c)2019 by ir. Marc Dendooven                 |');
    writeln('| V0.2 DEV                                      |');
    writeln('+-----------------------------------------------+');   
    writeln;
    load;
    IP := 0;
    RX[SP] := $100;
    while IP < segEnd do begin //fetch execute loop
        mon;
        IR := fetch; // IR := peek(IP); inc(IP)
        inc(cnt);
        debug(intToStr(cnt)+'> fetching instruction '+hexstr(IR,2)+' at '+hexstr(IP-1,4));
        w := boolean(IR and %1);
        d := (IR and %10) >> 1;
        case IR of
        $00..$03: begin mm_EG; i_ADD end;   
        $04,$05: begin mm_AI; i_ADD end;
        $08..$0B: begin mm_EG; i_OR end;
        $18..$1B: begin mm_EG; i_SBB end;
        $20..$23: begin mm_EG; i_AND end;
        $28..$2B: begin mm_EG; i_SUB end;
        $30..$33: begin mm_EG; i_XOR end;
        $38..$3B: begin mm_EG; i_CMP end;
        $3C,$3D: begin mm_AI; i_CMP end; //error('$3C - CMP AL Ib - nyi');
        $40..$47: i_INC_RX;
        $48..$4F: i_DEC_RX;
        $50..$57: i_PUSH_RX; 
        $58..$5F: i_POP_RX;
        $72,$74,$75,$76,$77,$79: i_Jcond; // $70..7F has same format with other flags
        $80..$83: begin mm_EI; GRP1 end;
        $86..$87: begin mm_EG; i_XCHG end;  
        $88..$8B: begin mm_EG; i_MOV end; 
        $90: debug('--NOP');
        $91..$97: i_XCHG_RX_AX; 
        $B0..$B7: i_MOV_R8_Ib;
        $B8..$BF: i_MOV_RX_Iw;
        $C3: i_RET;
        $C6,$C7: begin d := 0; mm_EI; i_MOV end; //d is not used as s here... set to 0
        $E8: i_CALL_Jv; 
        $EB: i_JMP_Jb;
        $F4: i_HLT;
        $F9: begin debug('--executing STC');FC := 1 end;
        $FE: GRP4;
        else
            error('instruction is not yet implemented')
        end
    end;
    writeln;
    error('debug - trying to execute outside codesegment')
end.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.