Jady's profile两尾鱼:子非鱼,安知鱼之乐PhotosBlogListsMore Tools Help

Blog


    February 13

    嵌入式操作系统一览

    • AMX (KADAK)
    • AvSYS Real-Time (Avocet Systems)
    • Blackhawk OS (Blackhawk)
    • BlueCat Linux (LynuxWorks)
    • BSD/OS (Wind River)
    • C Executive (JMI Software)
    • CMX-RTX, CMX-Tiny+, CMX-RTXS (CMX Systems)
    • Diamond (3L)
    • DR-DOS 7.03 (The SCO Group)
    • eCos (Red Hat)
    • Embedix RT (Lineo)
    • embOS (SEGGER)
    • ERCOSEK (ETAS)
    • eRTOS (JK Microsystems)
    • EUROS (EUROS Embedded Systems)
    • Eyrx (Eyring)
    • Fusion RTOS (DSP OS)
    • icWORKSHOP (Integrated Chipware)
    • INTEGRITY (Green Hills Software)
    • iRMX III, iRMX/INtime for Windows (TenAsys)
    • Jbed (esmertec)
    • Linux for Real-Time (OnCore Systems)
    • LynxOS (LynuxWorks)
    • mC/OS-II (Micrium)
    • Microwave OS-9 (RadiSys)
    • MontaVista Linux (MontaVista Software)
    • NetBSD Embedded (Wasabi Systems)
    • Neutrino (QNX Software Systems)
    • Nucleus uiPLUS, Nucleus OSEK, Nucleus PLUS (Accelerated Technology/Mentor Graphics)
    • On Time RTOS-32 (On Time Software)
    • OnCore OS (OnCore Systems)
    • OSE RTOS (OSE Systems)
    • OSEKturbo (Metrowerks/Motorola)
    • OSEKWorks (Wind River)
    • PDOS (Eyring)
    • pF/x (FORTH)
    • PharLap Real-time ETS Kernel (VenturCom)
    • pmDOS (Micro Digital)
    • Precise/MQX (ARC International)
    • PSMX Portable smx (Micro Digital)
    • pSOSystem 2.5/3 (Wind River)
    • PSX (JMI Software Systems)
    • PXROS (HighTec EDV-Systeme)
    • QNX (QNX Software Systems)
    • Quadros (RTXC)
    • QuickTask (Softools)
    • RAVEN (Aonix)
    • REAL/IX PX (MODCOMP)
    • Realogy Real-Time Architect (LiveDevices)
    • REALOS (Fujitsu Microelectronics)
    • Real-Time OS: DSP/BIOS (Texas Instruments)
    • Red Hat Embedded (Red Hat)
    • REDICE-Linux (REDSonic)
    • ROM-DOS (Datalight)
    • RTexec (Applied Dynamics International)
    • RTEMS (OAR)
    • RTKernel (On Time Software)
    • RTKernel-RISC (EBSnet)
    • RTX for Windows (VenturCom)
    • RTX51/RTX51 Tiny, RTX166/RTX166 Tiny (Keil)
    • Salvo (Pumpkin)
    • SKYmpx (SKY Computers)
    • smx/smx++ (Micro Digital)
    • Spartos (Ardro Engineering)
    • Starlight Linux (Auriga)
    • SuperTask (Lantronix)
    • TargetOS (Blunk Microsystems)
    • ThreadX (Express Logic)
    • Tics (TICS Realtime)
    • TimeSys Linux/RT, Real-Time Mach (TimeSys)
    • TronTask3.0 (Lantronix)
    • TTPos (TTTech Computertechnik)
    • TurboTask (Softools)
    • TxOS - Titanic (Incantation Systems)
    • T-Engine (iTron)
    • VRTX (Mentor Graphics)
    • VSPWorks (Wind River)
    • VxWorks, VxWorks AE (Wind River)
    • Windows CE .NET, Windows XP Embedded (Microsoft)

    来源:

    http://www.embedded.com/story/OEG20021212S0061

    July 11

    CPPUnit

    VC++下使用CPPUnit的最简单的步骤

    1,安装CPPUnit

    2,建立一个测试用的Project
    3,为每一个需要测试的Class设计一个相应的TestClass (派生于CppUnit::TestCase)
    4,在每一个TestClass中,设计多个TestCase
    TestCase一般是预先设计,这是XP的"Test优先原则"。
    发现一个Bug之后,一般为这个Bug也设计一个TestCase。
    (TestClass派生于CppUnit::TestCase,里面却包含多个TestCase,听起来也许有点容易糊涂)
    例 -----------------------------------------------------
    .h文件
    class SampleClassTest : public CppUnit::TestCase
    {
    private:
    CPPUNIT_TEST_SUITE(
    SampleClassTest); // 一个Test Class作为一个Test Suite
    CPPUNIT_TEST(TestCase1); // 在Test Suite中追加一个 Test Case
    CPPUNIT_TEST(TestCase2); // 在Test Suite中再追加一个 Test Case
    CPPUNIT_TEST_SUITE_END();

    public:
    SampleClassTest ();
    virtual ~SampleClassTest ();
    // 每一个TestCase开始之前都会被调用一次
    void setUp();
    // 每一个TestCase结束之后都会被调用一次
    void tearDown();
    protected:
    void TestCase1();
    void TestCase2();

    };

    .cpp文件
    CPPUNIT_TEST_SUITE_REGISTRATION(SampleClassTest); // 注册该Test Suite
    -----------------------------------------------------------
    5,测试用Project的Main/InitInstance中启动TestRunner,TestRunner可以对该Project中所有注册了的TestSuite进行测试。
    -----------------------------------------------------------
    CppUnit::MfcUi::TestRunner runner;
    runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() );
    runner.run();
    -----------------------------------------------------------
    参考:
    July 08

    从FrameWork的角度看Creational Pattern

    假设程序开发分成2层,第一层是FrameWork,第二层是Application。一个FrameWork可以在多个Application中使用。这样,FrameWork需要独立于Application,即FrameWork不应该需要看到Application的接口。

    假设FrameWork需要使用到一个类AbstractA,Application以AbstractA为基类设计派生类ConcreteA。
    1, 如果ConcreteA对象是由Application创建(Create)的,那么只要使用继承就可以了。不同的Application设计不同的ConcreteA,把ConcreteA对象的指针或者引用作为AbstractA传递给FrameWork就可以了。
    2, 如果ConcreteA对象是需要FrameWork创建的,那么可以考虑FactoryMethod。不同的Application设计不同的ConcreteA,以及相应的ConcreteCreatorA。Application把ConcreteCreatorA对象的指针或者引用作为AbstactCreatorA传递给FrameWork,FrameWork通过AbstactCreatorA的FactoryMethod创建ConcreteA对象。
    3, 比FactoryMethod更进一步,如果Application中需要多个AbstractA的派生类,比如ConcreteA1,ConcreteA2,ConcreteAn。为了避免需要相应的同样多的ConcreteCreatorA1,ConcreteCreatorA2…ConcreteCreatorAn,可以考虑Prototype。这样,Application只需要一个ConcreteCreatorA就可以创建多个AbstractA的派生类对象ConcreteA1,ConcreteA2…ConcreteAn。
    4, 如果一系列的AbstractA,AbstractB…AbstractN,相应的派生类对象都需要FrameWork创建。可以考虑AbstractFactory。AbstractFactory中可以采取FactoryMethod,也可以采取Prototype。
    5, 一般来说,AbstractFactory中的ConcreteFactory经常是Singleton
    June 08

    关于文字代码(character code)

    为了理解计算机处理文字的编码/表示,首先需要分清楚三个概念(这些概念经常被混淆)。

    1,character repertoire (字符列表)
    这是指某个特定的可表示的字符集合。

    例如:
    the Japanese syllabaries and ideographs of JIS X 0208 (CS 01058) [fixed]
    the Western European alphabets and symbols of Latin-1 (CS 00697) [fixed]
    the POSIX portable character repertoire [fixed]
    the IBM host Japanese repertoire (CS 01001) [fixed]
    the Windows Western European repertoire [open]
    the Unicode/10646 repertoire [open]

    2, character code (字符代码)
    把character repertoire中的每一个字符分别赋予一个非负的数字,建立一个字符与数字的一一对应关系。这些数字就是character code。

    character code中的数字并不一定是连续的,事实上,有些数字可以被保留作为control function (控制代码)。

    character code有很多别名:code position,code number, code value, code element, code point, code set value , code

    例如:JIS X 0208, ISO 8859-1,ISO 8859-2, ISO 8859-n, UNICODE等等

    3,character encoding (字符编码)
    把一个字符串相对应的character codes转换成计算机中的一串字节流的method/algorithm(方法/算法)称为character encoding。

    例如:JIS ENCODING, EUC ENCODING, ISO 8859-1,ISO 8859-2, ISO 8859-n, UTF-16, UTF-8等等

    这三个概念是分开的,他们之间可以是一对多的关系。比如,同一个character repertoire可以有不同的character codes;同一个 character repertoire/character codes 可以采取不同的character encoding。不过,有些标准同时规定了character repertoire/character codes/character encoding,建立了一一对应的关系,比如ISO 8859,Windows CodePages 等等。

    ★ Windows CodePages跟ISO 8859并不完全相等,DOS CodePages (OEM CodePages)差别更大。
    ★ ISO 2022 和 ISO 4873 为 8bits/7bits codes 建立了一个encoding的通用框架(general framework),很多标准都遵从这个框架(当然,一般只是框架中的一个子集);但Windows CodePages并不遵从这个框架。
    参考资料:
    June 01

    <<Design Pattern>> 读书笔记

    Builder
    Singleton


    Structural Patterns

    Behavioral Patterns
    May 24

    需求文档大纲

    下面是Alistair Cockburn列出的一个系统需求文档(System Requirments Document)的大纲。
    最详细的Requirment格式可以在Managing Requirements (Robertson and Robertson, Addison-Wesley, 1999).找到。不过,Requirment应该根据具体项目的具体情况进行合适的裁减。

    需要注意Use Case和Requirment的联系和区别:
    1,Use Case有很多用处,作为Requirment的一部分只是它的用处之一。
    2,Use Case是Requirment,但不是Requirment的全部,只是Requirment的一部分。

    从下面的大纲中可以看出,Use Case处于Requirment的第三章,它代表了系统的所有[功能]行为需求(behavioral requirements)。
    ---------------------------------------------------------

    A PLAUSIBLE REQUIREMENTS FILE OUTLINE
    一个需求文档大纲的例子

    Chapter 1. Purpose and scope 目的和范围
    1a. What is the overall scope and goal?
    整体的范围和目标
    1b. Stakeholders (who cares?)
    跟该系统有利益相关性的人
    1c. What is in scope, what is out of scope
    范围内和范围外的东西

    Chapter 2. The terms used / Glossary 用语

    Chapter 3. The use cases 用例
    3a. The primary actors and their general goals
    主要参与者与他们的目标
    3b. The business use cases (operations concepts)
    业务用例(操作概念上的用例)
    3c. The system use cases
    系统用例

    Chapter 4. The technology to be used 所需技术
    4a. What technology requirements are there for this system?
    该系统所需要的技术
    4b. What systems will this system interface with, with what requirements?、
    与其他系统的接口/需求

    Chapter 5. Other various requirements 其它需求
    5a. Development process 开发流程
    Q1. Who are the project participants?
    项目的参与者
    Q2. What values will be reflected in the project (simple, soon, fast, or flexible)?
    项目流程的采用的理念
    Q3. What feedback or project visibility do the users and sponsors wish?
    如何向用户反馈
    Q4. What can we buy, what must we build, what is our competition to this system?
    购买的模块,自己创建的模块,竞争对手
    Q5. What other process requirements are there (testing, installation, etc.)?
    其他项目流程需求
    Q6. What dependencies does the project operate under?
    项目的依赖性
    5b. Business rules 商业规则
    5c. Performance 性能
    5d. Operations, security, documentation 操作性,安全性,文档
    5e. Use and usability 使用和可用性
    5f. Maintenance and portability 维护与移植
    5g. Unresolved or deferred 其它未决的问题

    Chapter 6. Human backup, legal, political, organizational issues
    人员后备,法律,政治,政府相关的问题

    Q1. What is the human backup to system operation?
    系统发生失败的时候,如何通过人员后备的方法来进行弥补
    Q2. What legal, what political requirements are there?
    法律,政治相关的需求
    Q3. What are the human consequences of completing this system?
    完成该系统后,对相关人员产生的影响
    Q4. What are the training requirements?
    培训需求
    Q5. What assumptions, dependencies are there on the human environment?
    在人的环境中,该系统有什么假设,依赖性等等

    Chapter 7. Possible project plan 大体的项目计划
    ---------------------------------------------------------

    附:一些用语
    ---------------------------------------------------------
    SuD
    system under discussion 所讨论的系统
    Scope 范围
    What is really the system under discussion? 系统所讨论的是什么东西
    Stakeholder 关系人
    Someone or something with a vested interest in the behavior of the system under discussion (SuD).
    对该系统有直接利益关系的所有的人
    Primary actor 主要参与者
    The stakeholder who or which initiates an interaction with the SuD to achieve a goal.
    直接跟系统进行互动的关系人
    Actor 参与者
    Anyone or anything with behavior.
    所有跟系统有互动的人或物
    ---------------------------------------------------------
    参考资料:

    May 16

    C++点点滴滴

    ● 对象作为参数传给函数,以及函数返回对象的问题

    1, 当对象作为参数直接传给函数时(passing object by value),作为该对象的一个拷贝,一个新的对象会产生。
    但是需要注意的是:
    该新的对象被自动创建的时候,构造函数(constructor)并不被调用,而是复制构造函数(copy constructor)被调用;因为构造函数是初始化一个对象,而作为传入函数的参数,是现有对象的一个拷贝。
    当函数结束的时候,为了参数而新创建的对象的生命周期也会结束,因此,这个时候,对象的析构函数(destructor)会被调用。

    2, 当函数返回一个对象的时候,需要注意的是,如果该返回值不被明确地赋值给一个对象的话,一个临时的对象会被自动创建,用于其他可能的计算;同样的,对象的返回(无论是否临时对象),对象的复制构造函数会被调用,而不是构造函数;当临时对象完成使命(返回 has been returned)后,对象的析构函数(destructor)会被调用。

    因此,对象作为参数传给函数,以及函数返回对象的时候,特别需要注意对象的成员中有指针的情况。

    ● 关于复制构造函数(copy constructor)

    当一个变量通过一个现有的对象被创建的时候,复制构造函数会被调用。

    存在于下面三种情况(注意,赋值操作的时候,并不会被调用):
    1,声明一个变量的时候,同时初始化该变量
    ---------------------------------------------------------------------------------
    Person q("Mickey"); // 构造函数被调用
    Person r(p); // 复制构造函数被调用
    Person p = q; // 复制构造函数被调用
    p = q; // 这是一个赋值操作, 构造函数和复制构造函数都不被调用
    ---------------------------------------------------------------------------------
    2, 当对象作为参数直接传给函数时(passing object by value)
    3, 当函数返回一个对象的时候

    参考: http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html

    ● 关于运算符重载(operator overloading)

    运算符重载可以通过成员函数(member functions)和友好函数(friend functions)实现。
    但是有以下的限制:
    1, 不能改变运算符的优先级
    2, 不能创建新的运算符
    3, 不能重载 :: sizeof ?: . **
    (Thinking in C++: . .* **)
    4, 重载+并不意味着同时重载了+=,其他-=等也是同样
    5, 重载 =,[],-> ,() 运算符的时候,只能通过成员函数实现,从而强制使得左操作数类型是所定义的类。
    6, ++ 和 -- 的重载需要特殊的处理 (a++/a--和++a/--a的区别)
    7, = 的重载需要特殊的考虑 (自我判断,指针的释放和分配)

    Thinking in C++:
    Murray 对于操作符重载是否使用成员函数有如下建议:
    操作符 建议
    -------------------------------------------------
    所有的一元符号 成员函数
    -------------------------------------------------
    = ( ) [ ] –> –>* 必须是成员函数
    -------------------------------------------------
    += –= /= *= ^=
    &= |= %= >>= <<= 成员函数
    -------------------------------------------------
    所有的二元符号 非成员函数

    ● 关于函数隐藏
    子类可以通过改变返回值或者参数来隐藏父类的函数,但如果该函数是虚拟函数的话,则只能通过改变参数而不能通过改变返回值来隐藏该函数,因为相同参数的虚拟函数只能覆盖而不能隐藏,而覆盖只能返回相同的返回值类型(或者该类型的派生类)。
    ● 关于继承
    1,构造函数,复制构造函数,析构函数,赋值(=)操作符号函数并不会自动被继承,而是被综合(synthesized)
    2,如果子类明确定义了复制构造函数/赋值操作符号函数,必须明确调用父类的相应的复制构造函数/赋值操作符号函数,否则父类的缺省构造函数会被调用。
    3,赋值操作符号函数只综合相同类型对象的赋值。

    From <<Thinking in C++>>
    ----------------------------------------------------------------------------------------------

    //:! :CopyRight.txt(c) 1995-2004 MindView, Inc. All rights reserved.
    //: C14:SynthesizedFunctions.cpp
    // Functions that are synthesized by the compiler
    #include <iostream>
    using namespace std;

    class GameBoard {
    public:
    GameBoard() { cout << "GameBoard()\n"; }
    GameBoard(const GameBoard&) {
    cout << "GameBoard(const GameBoard&)\n";
    }
    GameBoard& operator=(const GameBoard&) {
    cout << "GameBoard::operator=()\n";
    return *this;
    }
    ~GameBoard() { cout << "~GameBoard()\n"; }
    };

    class Game {
    GameBoard gb; // Composition
    public:
    // Default GameBoard constructor called:
    Game() { cout << "Game()\n"; }
    // You must explicitly call the GameBoard
    // copy-constructor or the default constructor
    // is automatically called instead:
    Game(const Game& g) : gb(g.gb) {
    cout << "Game(const Game&)\n";
    }
    Game(int) { cout << "Game(int)\n"; }
    Game& operator=(const Game& g) {
    // You must explicitly call the GameBoard
    // assignment operator or no assignment at
    // all happens for gb!
    gb = g.gb;
    cout << "Game::operator=()\n";
    return *this;
    }
    class Other {}; // Nested class
    // Automatic type conversion:
    operator Other() const {
    cout << "Game::operator Other()\n";
    return Other();
    }
    ~Game() { cout << "~Game()\n"; }
    };

    class Chess : public Game {};

    void f(Game::Other) {}

    class Checkers : public Game {
    public:
    // Default base-class constructor called:
    Checkers() { cout << "Checkers()\n"; }
    // You must explicitly call the base-class
    // copy constructor or the default constructor
    // will be automatically called instead:
    Checkers(const Checkers& c) : Game(c) {
    cout << "Checkers(const Checkers& c)\n";
    }
    Checkers& operator=(const Checkers& c) {
    // You must explicitly call the base-class
    // version of operator=() or no base-class
    // assignment will happen:
    Game::operator=(c);
    cout << "Checkers::operator=()\n";
    return *this;
    }
    };

    int main() {
    Chess d1; // Default constructor
    Chess d2(d1); // Copy-constructor
    //! Chess d3(1); // Error: no int constructor
    d1 = d2; // Operator= synthesized
    f(d1); // Type-conversion IS inherited
    Game::Other go;
    //! d1 = go; // Operator= not synthesized
    // for differing types
    Checkers c1, c2(c1);
    c1 = c2;
    } ///:~
    --------------------------------------------------------------
    GameBoard()
    Game()
    GameBoard(const GameBoard&)
    Game(const Game&)
    GameBoard::operator=()
    Game::operator=()
    Game::operator Other()
    GameBoard()
    Game()
    Checkers()
    GameBoard(const GameBoard&)
    Game(const Game&)
    Checkers(const Checkers& c)
    GameBoard::operator=()
    Game::operator=()
    Checkers::operator=()
    ~Game()
    ~GameBoard()
    ~Game()
    ~GameBoard()
    ~Game()
    ~GameBoard()
    ~Game()
    ~GameBoard()
    --------------------------------------------------------------


    ● 关于异常
    1,当一个异常在所有的层次都不被捕获的时候,terminate()会被调用
    2,当一个局部变量的析构函数中抛出异常的时候,terminate()会被调用;当一个全局变量或者static变量的构造函数或者析构函数种抛出异常的时候,terminate()会被调用。
    3,当一个对象在构造函数中抛出异常的时候,它的析构函数不会被调用。

    参考资料:
    http://www.fredosaurus.com/notes-cpp/
    <<Thinking in C++>> 2ed 2000 by Bruce Eckel

    C/C++中align的问题

    在C/C++编程中,有一个align的问题经常被忽略。所谓align的问题,就是指通过对原始数据类型按边界对齐,CPU可以达到更好的访问效率。align的基本原则是,数据类型以本身的size作为边界对齐。比如,char按1byte对齐,short按2byte对齐,int按4byte对齐等等。

    在定义structure,union,class的时候,需要考虑到这个align的问题。如果访问了Unaligned的数据,不同的CPU和不同的OS会有不同的处理,在多平台开发中尤其要注意这个问题。

    x86对Unaligned的数据的访问进行了处理,然而对性能有影响。一些RISC类型的CPU在对Unaligned的数据进行访问的时候,会发生非正常中断的现象,一些RISC类型的CPU会发出一个异常给OS,由OS决定是否处理。

    概括来说,对Unaligned的数据的访问,有下面四种情况:
    1,CPU以性能为代价,对Unaligned的数据的访问进行处理。
    2,CPU抛出异常给OS,OS对Unaligned的数据的访问进行处理。
    3,CPU抛出异常没有被OS处理,这样会产生非正常中断等严重的问题产生。
    4,编译器对Unaligned的数据的访问进行处理,同样必须以性能为代价。

    对于编译器对Unaligned的数据进行处理,为了达到align的目的,自动加入了pading的数据。这时候需要注意这些pading的数据,尤其是使用指针的时候,通常会得到一些预料之外的结果。

    下面是一个在VC++下的例子:

    =============================================================
    #include "stdafx.h"
    #include <stdio.h>
    #pragma pack(1)
    struct s1 {
    char i;
    short j;
    int k;
    };
    struct s2 {
    char i;
    struct s1 j;
    };
    #pragma pack()
    /**************************
    struct s3 {
    char i;
    char _pad[1];
    short j;
    int k;
    };
    **************************/
    struct s3 {
    char i;
    short j;
    int k;
    };
    /**************************
    struct s4 {
    char i;
    char _pad[3];
    struct s3 j;
    };
    **************************/
    struct s4 {
    char i;
    struct s3 j;
    };
    /**************************
    struct s5 {
    char i;
    char _pad1[3];
    int k;
    short j;
    char _pad2[2];
    };
    **************************/
    struct s5 {
    char i;
    int k;
    short j;
    };
    struct s1 t1;
    struct s2 t2;
    struct s3 t3;
    struct s4 t4;
    struct s5 t5;
    int main(int argc, char* argv[])
    {
    int i;
    char *pi;
    short *pj;
    int *pk;
    // 7
    /***************************
    struct s1 {
    char i;
    short j;
    int k;
    };
    ***************************/
    i = sizeof(t1);
    printf("%d\n", i);
    // 8
    /**************************
    struct s2 {
    char i;
    struct s1 j;
    };
    **************************/
    i = sizeof(t2);
    printf("%d\n", i);
    // 8
    /**************************
    struct s3 {
    char i;
    char _pad[1];
    short j;
    int k;
    };
    **************************/
    i = sizeof(t3);
    printf("%d\n", i);
    // 12
    /**************************
    struct s4 {
    char i;
    char _pad[3];
    struct s3 j;
    };
    **************************/
    i = sizeof(t4);
    printf("%d\n", i);
    // 12
    /**************************
    struct s5 {
    char i;
    char _pad1[3];
    int k;
    short j;
    char _pad2[2];
    };
    **************************/
    i = sizeof(t5);
    printf("%d\n", i);
    t1.i = 1;
    t1.j = 2;
    t1.k = 3;
    // 1, 2, 3
    pi = &t1.i;
    pj = (short* )(pi + 1);
    pk = (int* )(pi + 3);
    printf("%d, %d, %d\n", *pi, *pj, *pk);
    t3.i = 1;
    t3.j = 2;
    t3.k = 3;
    // 1, 512, 768
    pi = &t3.i;
    pj = (short* )(pi + 1);
    pk = (int* )(pi + 3);
    printf("%d, %d, %d\n", *pi, *pj, *pk);
    return 0;
    }
    /************ OUTPUT ************
    7
    8
    8
    12
    12
    1, 2, 3
    1, 512, 768
    ******************************/
    =============================================================
    参考资料:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_PREDIR_pack.asp
    Bret S. Pehrson : Unaligned Data Access